diff --git a/.dart_tool/extension_discovery/devtools.json b/.dart_tool/extension_discovery/devtools.json new file mode 100644 index 00000000..ae1a36a6 --- /dev/null +++ b/.dart_tool/extension_discovery/devtools.json @@ -0,0 +1 @@ +{"version":2,"entries":[{"package":"sf_app_platform_mono_repo","rootUri":"../","packageUri":"lib/"}]} \ No newline at end of file diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json index e15b8038..3b00a9d9 100644 --- a/.dart_tool/package_config.json +++ b/.dart_tool/package_config.json @@ -3,349 +3,349 @@ "packages": [ { "name": "ansi_styles", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/ansi_styles-0.3.2+1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/ansi_styles-0.3.2+1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "args", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/args-2.7.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/args-2.7.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "async", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.13.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/async-2.13.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "characters", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/characters-1.4.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/characters-1.4.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "charcode", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/charcode-1.4.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/charcode-1.4.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "checked_yaml", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/checked_yaml-2.0.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/checked_yaml-2.0.4", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "cli_launcher", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cli_launcher-0.3.2+1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cli_launcher-0.3.2+1", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "cli_util", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cli_util-0.4.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cli_util-0.4.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "collection", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/collection-1.19.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "conventional_commit", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/conventional_commit-0.6.1+1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/conventional_commit-0.6.1+1", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "ffi", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/ffi-2.1.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/ffi-2.1.4", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "file", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/file-7.0.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/file-7.0.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "flutter", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "flutter_secure_storage", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage-9.2.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "flutter_secure_storage_linux", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "flutter_secure_storage_macos", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.3", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "flutter_secure_storage_platform_interface", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage_platform_interface-1.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_platform_interface-1.1.2", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "flutter_secure_storage_web", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "flutter_secure_storage_windows", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "flutter_web_plugins", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter_web_plugins", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter_web_plugins", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "glob", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/glob-2.1.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/glob-2.1.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "graphs", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/graphs-2.3.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/graphs-2.3.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "http", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http-1.5.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http-1.5.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "http_parser", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http_parser-4.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http_parser-4.1.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "io", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/io-1.0.5", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/io-1.0.5", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "js", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/js-0.6.7", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/js-0.6.7", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "json_annotation", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/json_annotation-4.9.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/json_annotation-4.9.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "material_color_utilities", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/material_color_utilities-0.11.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "melos", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/melos-6.3.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/melos-6.3.3", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "meta", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.16.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/meta-1.16.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "mustache_template", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/mustache_template-2.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/mustache_template-2.0.2", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "path", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path-1.9.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "path_provider", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider-2.1.5", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider-2.1.5", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "path_provider_android", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_android-2.2.20", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_android-2.2.20", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "path_provider_foundation", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_foundation-2.4.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.3", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "path_provider_linux", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.1", + "rootUri": "file:///Users/juliandalcalaf/.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/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_platform_interface-2.1.2", + "rootUri": "file:///Users/juliandalcalaf/.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/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_windows-2.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "platform", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/platform-3.1.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/platform-3.1.6", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "plugin_platform_interface", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/plugin_platform_interface-2.1.8", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "pool", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pool-1.5.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pool-1.5.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "process", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/process-5.0.5", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/process-5.0.5", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "prompts", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/prompts-2.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/prompts-2.0.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "pub_semver", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pub_semver-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pub_semver-2.2.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "pub_updater", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pub_updater-0.5.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pub_updater-0.5.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "pubspec_parse", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_parse-1.5.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pubspec_parse-1.5.0", "packageUri": "lib/", "languageVersion": "3.6" }, { "name": "sky_engine", - "rootUri": "file:///C:/Program%20Files/Flutter/bin/cache/pkg/sky_engine", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/bin/cache/pkg/sky_engine", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "source_span", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_span-1.10.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "stack_trace", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stack_trace-1.12.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "string_scanner", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.4.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/string_scanner-1.4.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "term_glyph", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/term_glyph-1.2.2", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "typed_data", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/typed_data-1.4.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/typed_data-1.4.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "vector_math", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_math-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_math-2.2.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "web", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web-1.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web-1.1.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "win32", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/win32-5.15.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/win32-5.15.0", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "xdg_directories", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/xdg_directories-1.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "yaml", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/yaml-3.1.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/yaml-3.1.3", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "yaml_edit", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/yaml_edit-2.2.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/yaml_edit-2.2.2", "packageUri": "lib/", "languageVersion": "3.1" }, @@ -358,7 +358,7 @@ ], "generator": "pub", "generatorVersion": "3.9.2", - "flutterRoot": "file:///C:/Program%20Files/Flutter", - "flutterVersion": "3.35.6", - "pubCache": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache" + "flutterRoot": "file:///Users/juliandalcalaf/Development/flutter", + "flutterVersion": "3.35.7", + "pubCache": "file:///Users/juliandalcalaf/.pub-cache" } diff --git a/.dart_tool/pub/bin/melos/melos.dart-3.9.2.snapshot b/.dart_tool/pub/bin/melos/melos.dart-3.9.2.snapshot index 2c19732b..4d144da8 100644 Binary files a/.dart_tool/pub/bin/melos/melos.dart-3.9.2.snapshot and b/.dart_tool/pub/bin/melos/melos.dart-3.9.2.snapshot differ diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index b4eaa85f..a52794ea 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage-9.2.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.4.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"flutter_secure_storage","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage-9.2.4\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.2.20\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"flutter_secure_storage_macos","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_macos-3.1.3\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.4.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"flutter_secure_storage_linux","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_linux-1.2.3\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.2.1\\\\","native_build":false,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"flutter_secure_storage_windows","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_windows-3.1.2\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.3.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false}],"web":[{"name":"flutter_secure_storage_web","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\flutter_secure_storage_web-1.2.1\\\\","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":["flutter_secure_storage_linux","flutter_secure_storage_macos","flutter_secure_storage_web","flutter_secure_storage_windows"]},{"name":"flutter_secure_storage_linux","dependencies":[]},{"name":"flutter_secure_storage_macos","dependencies":[]},{"name":"flutter_secure_storage_web","dependencies":[]},{"name":"flutter_secure_storage_windows","dependencies":["path_provider"]},{"name":"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":[]}],"date_created":"2026-03-09 09:15:02.914305","version":"3.35.6","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.3/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"flutter_secure_storage","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_android-2.2.20/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"flutter_secure_storage_macos","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.3/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"flutter_secure_storage_linux","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"flutter_secure_storage_windows","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false}],"web":[{"name":"flutter_secure_storage_web","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":["flutter_secure_storage_linux","flutter_secure_storage_macos","flutter_secure_storage_web","flutter_secure_storage_windows"]},{"name":"flutter_secure_storage_linux","dependencies":[]},{"name":"flutter_secure_storage_macos","dependencies":[]},{"name":"flutter_secure_storage_web","dependencies":[]},{"name":"flutter_secure_storage_windows","dependencies":["path_provider"]},{"name":"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":[]}],"date_created":"2026-03-13 09:52:54.635963","version":"3.35.7","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 73caafef..b1a096bd 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -17,7 +17,6 @@ - diff --git a/.idea/runConfigurations/melos_flutter_run_flutter_treezor_entrust_sdk_bridge_example.xml b/.idea/runConfigurations/melos_flutter_run_flutter_treezor_entrust_sdk_bridge_example.xml index 8ed30c3e..4b63d7a9 100644 --- a/.idea/runConfigurations/melos_flutter_run_flutter_treezor_entrust_sdk_bridge_example.xml +++ b/.idea/runConfigurations/melos_flutter_run_flutter_treezor_entrust_sdk_bridge_example.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/.idea/runConfigurations/melos_flutter_run_sf_app_platform.xml b/.idea/runConfigurations/melos_flutter_run_sf_app_platform.xml index c7845145..e2a9ffba 100644 --- a/.idea/runConfigurations/melos_flutter_run_sf_app_platform.xml +++ b/.idea/runConfigurations/melos_flutter_run_sf_app_platform.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/.idea/runConfigurations/melos_flutter_test_design_system.xml b/.idea/runConfigurations/melos_flutter_test_design_system.xml index 42cc1035..5f9f3264 100644 --- a/.idea/runConfigurations/melos_flutter_test_design_system.xml +++ b/.idea/runConfigurations/melos_flutter_test_design_system.xml @@ -1,7 +1,7 @@ - \ No newline at end of file diff --git a/.idea/runConfigurations/melos_flutter_test_flutter_treezor_entrust_sdk_bridge.xml b/.idea/runConfigurations/melos_flutter_test_flutter_treezor_entrust_sdk_bridge.xml index 3dfe0410..ac06fca7 100644 --- a/.idea/runConfigurations/melos_flutter_test_flutter_treezor_entrust_sdk_bridge.xml +++ b/.idea/runConfigurations/melos_flutter_test_flutter_treezor_entrust_sdk_bridge.xml @@ -1,7 +1,7 @@ - \ No newline at end of file diff --git a/apps/mobile_app/android/app/src/main/AndroidManifest.xml b/apps/mobile_app/android/app/src/main/AndroidManifest.xml index 74727fc6..787e42db 100644 --- a/apps/mobile_app/android/app/src/main/AndroidManifest.xml +++ b/apps/mobile_app/android/app/src/main/AndroidManifest.xml @@ -4,6 +4,7 @@ + UIStatusBarHidden + NSContactsUsageDescription + Necesitamos acceso a tus contactos para seleccionar números de teléfono. NSCameraUsageDescription Necesitamos la cámara para escanear códigos QR NSLocationWhenInUseUsageDescription diff --git a/apps/mobile_app/lib/navigation/app_router.dart b/apps/mobile_app/lib/navigation/app_router.dart index a1531132..0aa96c87 100644 --- a/apps/mobile_app/lib/navigation/app_router.dart +++ b/apps/mobile_app/lib/navigation/app_router.dart @@ -26,7 +26,7 @@ late final GoRouter appRouter; void configureAppRouter() { appRouter = GoRouter( navigatorKey: rootNavigatorKey, - initialLocation: AppRoutes.controlPanel, + initialLocation: AppRoutes.onboarding, debugLogDiagnostics: true, routes: [ GoRoute( @@ -94,10 +94,27 @@ void configureAppRouter() { name: 'device_management', pageBuilder: DeviceManagementBuilder().buildPage, routes: [ + GoRoute( + path: 'scheduled_activities', + name: 'scheduled_activities', + pageBuilder: const ScheduledActivitiesBuilder().buildPage, + ), GoRoute( path: 'contacts', name: 'contacts', - pageBuilder: ContactsBuilder().buildPage, + pageBuilder: const ContactsBuilder().buildPage, + routes: [ + GoRoute( + path: 'edit/:contactId', + name: 'edit_contact', + pageBuilder: const EditContactBuilder().buildPage, + ), + ], + ), + GoRoute( + path: 'health', + name: 'health', + pageBuilder: const HealthBuilder().buildPage, ), GoRoute( path: 'remote_connection', @@ -114,6 +131,16 @@ void configureAppRouter() { name: 'rewards', pageBuilder: RewardsBuilder().buildPage, ), + GoRoute( + path: 'activity_meter', + name: 'activity_meter', + pageBuilder: const ActivityMeterBuilder().buildPage, + ), + GoRoute( + path: 'apps_use', + name: 'apps_use', + pageBuilder: const AppsUseBuilder().buildPage, + ), ], ), ], @@ -131,7 +158,7 @@ void configureAppRouter() { StatefulShellBranch( routes: [ GoRoute( - path: '${ AppRoutes.legacyDashboard}/chat', + path: '${AppRoutes.legacyDashboard}/chat', name: 'legacy_chat', pageBuilder: (context, state) => MaterialPage( key: state.pageKey, @@ -150,80 +177,80 @@ void configureAppRouter() { pageBuilder: SettingsBuilder().buildPage, routes: [ GoRoute( - path: AppRoutes.alarm, + path: 'alarm', name: 'alarm', pageBuilder: AlarmBuilder().buildPage, ), - /*GoRoute ( - path: AppRoutes.appStore, - name: 'app_store', - // pageBuilder: AppStoreBuilder().buildPage, - ), - GoRoute ( - path: AppRoutes.battery, - name: 'battery', - // pageBuilder: BatteryBuilder().buildPage, - ), - GoRoute ( - path: AppRoutes.blockPhone, - name: 'block_phone', - // pageBuilder: BlockPhoneBuilder().buildPage, - ), - GoRoute ( - path: AppRoutes.disableFunctions, - name: 'disable_functions', - // pageBuilder: DisableFunctionsBuilder().buildPage, - ), - GoRoute ( - path: AppRoutes.language, - name: 'language', - // pageBuilder: LanguageBuilder().buildPage, - ), - GoRoute ( - path: AppRoutes.legacyNotifications, - name: 'legacy_notifications', - // pageBuilder: LegacyNotificationsBuilder().buildPage, - ),*/ - GoRoute ( - path: AppRoutes.remoteManagement, + GoRoute( + path: 'remote_management', name: 'remote_management', pageBuilder: RemoteManagementBuilder().buildPage, ), - /*GoRoute ( - path: AppRoutes.remoteOnOff, - name: 'remote_on_off', - // pageBuilder: RemoteOnOffBuilder().buildPage, - ), - GoRoute ( - path: AppRoutes.smsAlert, - name: 'sms_alert', - // pageBuilder: SmsAlertBuilder().buildPage, - ),*/ - GoRoute ( - path: AppRoutes.sosContacts, + GoRoute( + path: 'sos_agenda', name: 'sos_agenda', pageBuilder: SosContactsBuilder().buildPage, ), - GoRoute ( - path: AppRoutes.sound, + GoRoute( + path: 'sound', name: 'sound', pageBuilder: SoundBuilder().buildPage, ), - /*GoRoute ( - path: AppRoutes.syncClock, + GoRoute( + path: 'sync_clock', name: 'sync_clock', - // pageBuilder: SyncClockBuilder().buildPage, + pageBuilder: SyncClockBuilder().buildPage, ), - GoRoute ( - path: AppRoutes.timezone, + GoRoute( + path: 'app_store', + name: 'app_store', + pageBuilder: AppStoreBuilder().buildPage, + ), + GoRoute( + path: 'battery', + name: 'battery', + pageBuilder: BatteryBuilder().buildPage, + ), + GoRoute( + path: 'block_phone', + name: 'block_phone', + pageBuilder: BlockPhoneBuilder().buildPage, + ), + GoRoute( + path: 'disable_functions', + name: 'disable_functions', + pageBuilder: DisableFunctionsBuilder().buildPage, + ), + GoRoute( + path: 'language', + name: 'language', + pageBuilder: LanguageBuilder().buildPage, + ), + GoRoute( + path: 'legacy_notifications', + name: 'legacy_notifications', + pageBuilder: LegacyNotificationsBuilder().buildPage, + ), + GoRoute( + path: 'remote_on_off', + name: 'remote_on_off', + pageBuilder: RemoteOnOffBuilder().buildPage, + ), + GoRoute( + path: 'sms_alert', + name: 'sms_alert', + pageBuilder: SmsAlertBuilder().buildPage, + ), + GoRoute( + path: 'timezone', name: 'timezone', - // pageBuilder: TimezoneBuilder().buildPage, + pageBuilder: TimezoneBuilder().buildPage, ), - GoRoute ( - path: AppRoutes.wifiSettings, + GoRoute( + path: 'wifi_settings', name: 'wifi_settings', - // pageBuilder: WifiSettingsBuilder().buildPage, - ),*/ + pageBuilder: WifiSettingsBuilder().buildPage, + ), ], ), ], diff --git a/apps/mobile_app/pubspec.lock b/apps/mobile_app/pubspec.lock index a3ae34d1..de07dea0 100644 --- a/apps/mobile_app/pubspec.lock +++ b/apps/mobile_app/pubspec.lock @@ -406,6 +406,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_contacts: + dependency: transitive + description: + name: flutter_contacts + sha256: "388d32cd33f16640ee169570128c933b45f3259bddbfae7a100bb49e5ffea9ae" + url: "https://pub.dev" + source: hosted + version: "1.1.9+2" flutter_launcher_icons: dependency: "direct dev" description: diff --git a/apps/mobile_app/pubspec_overrides.yaml b/apps/mobile_app/pubspec_overrides.yaml index a87b35e2..f25a1e73 100644 --- a/apps/mobile_app/pubspec_overrides.yaml +++ b/apps/mobile_app/pubspec_overrides.yaml @@ -43,7 +43,7 @@ dependency_overrides: sca_treezor: path: ../../packages/sca_treezor settings: - path: ..\\..\\modules\\legacy\\modules\\settings + path: ../../modules/legacy/modules/settings sf_infrastructure: path: ../../packages/sf_infrastructure sf_localizations: diff --git a/modules/activity/.dart_tool/extension_discovery/devtools.json b/modules/activity/.dart_tool/extension_discovery/devtools.json new file mode 100644 index 00000000..dcdbc0fa --- /dev/null +++ b/modules/activity/.dart_tool/extension_discovery/devtools.json @@ -0,0 +1 @@ +{"version":2,"entries":[{"package":"design_system","rootUri":"../../../packages/design_system/","packageUri":"lib/"},{"package":"flutter_treezor_entrust_sdk_bridge","rootUri":"../../../packages/flutter_treezor_entrust_sdk_bridge/","packageUri":"lib/"},{"package":"fonts","rootUri":"../../../packages/fonts/","packageUri":"lib/"},{"package":"get_it","rootUri":"file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/get_it-9.2.0/","packageUri":"lib/","config":{"name":"get_it","issueTracker":"https://github.com/fluttercommunity/get_it/issues","version":"0.0.1","materialIconCodePoint":"0xe189"}},{"package":"sca_treezor","rootUri":"../../../packages/sca_treezor/","packageUri":"lib/"},{"package":"sf_infrastructure","rootUri":"../../../packages/sf_infrastructure/","packageUri":"lib/"},{"package":"sf_localizations","rootUri":"../../../packages/sf_localizations/","packageUri":"lib/"},{"package":"sf_shared","rootUri":"../../../packages/sf_shared/","packageUri":"lib/"},{"package":"shared_preferences","rootUri":"file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences-2.5.4/","packageUri":"lib/","config":{"name":"shared_preferences","issueTracker":"https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+shared_preferences%22","version":"1.0.0","materialIconCodePoint":"0xe683"}},{"package":"utils","rootUri":"../../../packages/utils/","packageUri":"lib/"},{"package":"activity","rootUri":"../","packageUri":"lib/"}]} \ No newline at end of file diff --git a/modules/activity/.dart_tool/package_config.json b/modules/activity/.dart_tool/package_config.json index e46c1c0e..416e3072 100644 --- a/modules/activity/.dart_tool/package_config.json +++ b/modules/activity/.dart_tool/package_config.json @@ -3,163 +3,163 @@ "packages": [ { "name": "_fe_analyzer_shared", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/_fe_analyzer_shared-85.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-85.0.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "analyzer", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/analyzer-7.7.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/analyzer-7.7.1", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "archive", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/archive-4.0.9", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/archive-4.0.9", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "args", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/args-2.7.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/args-2.7.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "async", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.13.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/async-2.13.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "boolean_selector", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/boolean_selector-2.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/boolean_selector-2.1.2", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "build", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build-3.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build-3.1.0", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "build_config", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_config-1.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_config-1.2.0", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "build_daemon", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_daemon-4.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_daemon-4.1.1", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "build_resolvers", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_resolvers-3.0.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_resolvers-3.0.3", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "build_runner", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_runner-2.7.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_runner-2.7.1", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "build_runner_core", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_runner_core-9.3.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_runner_core-9.3.1", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "built_collection", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/built_collection-5.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/built_collection-5.1.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "built_value", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/built_value-8.12.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/built_value-8.12.3", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "characters", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/characters-1.4.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/characters-1.4.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "checked_yaml", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/checked_yaml-2.0.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/checked_yaml-2.0.4", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "cli_config", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cli_config-0.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cli_config-0.2.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "clock", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/clock-1.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/clock-1.1.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "code_builder", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/code_builder-4.11.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/code_builder-4.11.1", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "collection", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/collection-1.19.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "confetti", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/confetti-0.7.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/confetti-0.7.0", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "convert", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/convert-3.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/convert-3.1.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "cookie_jar", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cookie_jar-4.0.8", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cookie_jar-4.0.8", "packageUri": "lib/", "languageVersion": "2.15" }, { "name": "country_code_picker", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/country_code_picker-3.4.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/country_code_picker-3.4.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "coverage", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/coverage-1.15.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/coverage-1.15.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "crypto", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/crypto-3.0.7", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/crypto-3.0.7", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "dart_style", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dart_style-3.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dart_style-3.1.1", "packageUri": "lib/", "languageVersion": "3.7" }, @@ -171,91 +171,91 @@ }, { "name": "diacritic", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/diacritic-0.1.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/diacritic-0.1.6", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "dio", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dio-5.9.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dio-5.9.1", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "dio_cookie_manager", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dio_cookie_manager-3.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dio_cookie_manager-3.3.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "dio_web_adapter", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dio_web_adapter-2.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dio_web_adapter-2.1.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "equatable", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/equatable-2.0.8", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/equatable-2.0.8", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "fake_async", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/fake_async-1.3.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "ffi", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/ffi-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/ffi-2.2.0", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "file", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/file-7.0.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/file-7.0.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "fixnum", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/fixnum-1.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/fixnum-1.1.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "fl_chart", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/fl_chart-1.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/fl_chart-1.1.1", "packageUri": "lib/", "languageVersion": "3.6" }, { "name": "flutter", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "flutter_lints", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_lints-5.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_lints-5.0.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "flutter_riverpod", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_riverpod-3.2.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_riverpod-3.2.1", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "flutter_svg", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_svg-2.2.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_svg-2.2.3", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "flutter_test", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter_test", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter_test", "packageUri": "lib/", "languageVersion": "3.8" }, @@ -267,7 +267,7 @@ }, { "name": "flutter_web_plugins", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter_web_plugins", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter_web_plugins", "packageUri": "lib/", "languageVersion": "3.8" }, @@ -279,259 +279,259 @@ }, { "name": "freezed", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/freezed-3.2.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/freezed-3.2.3", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "freezed_annotation", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/freezed_annotation-3.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/freezed_annotation-3.1.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "frontend_server_client", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/frontend_server_client-4.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/frontend_server_client-4.0.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "get_it", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/get_it-9.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/get_it-9.2.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "glob", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/glob-2.1.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/glob-2.1.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "go_router", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/go_router-17.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/go_router-17.1.0", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "graphs", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/graphs-2.3.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/graphs-2.3.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "http", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http-1.6.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http-1.6.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "http_multi_server", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http_multi_server-3.2.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http_multi_server-3.2.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "http_parser", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http_parser-4.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http_parser-4.1.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "intl", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/intl-0.20.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/intl-0.20.2", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "io", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/io-1.0.5", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/io-1.0.5", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "js", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/js-0.7.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/js-0.7.2", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "json_annotation", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/json_annotation-4.9.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/json_annotation-4.9.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "json_serializable", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/json_serializable-6.11.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/json_serializable-6.11.2", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "leak_tracker", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker-11.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/leak_tracker-11.0.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "leak_tracker_flutter_testing", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.10", + "rootUri": "file:///Users/juliandalcalaf/.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/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_testing-3.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "lints", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/lints-5.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/lints-5.1.1", "packageUri": "lib/", "languageVersion": "3.6" }, { "name": "logging", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/logging-1.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/logging-1.3.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "lottie", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/lottie-3.3.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/lottie-3.3.2", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "matcher", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/matcher-0.12.17", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/matcher-0.12.17", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "material_color_utilities", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/material_color_utilities-0.11.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "meta", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.16.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/meta-1.16.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "mime", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/mime-2.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/mime-2.0.0", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "node_preamble", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/node_preamble-2.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/node_preamble-2.0.2", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "package_config", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/package_config-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/package_config-2.2.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "path", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path-1.9.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "path_parsing", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_parsing-1.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_parsing-1.1.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "path_provider", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider-2.1.5", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider-2.1.5", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "path_provider_android", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_android-2.2.22", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_android-2.2.22", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "path_provider_foundation", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_foundation-2.5.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_foundation-2.5.1", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "path_provider_linux", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.1", + "rootUri": "file:///Users/juliandalcalaf/.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/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_platform_interface-2.1.2", + "rootUri": "file:///Users/juliandalcalaf/.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/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_windows-2.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "petitparser", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/petitparser-7.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/petitparser-7.0.2", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "platform", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/platform-3.1.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/platform-3.1.6", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "plugin_platform_interface", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/plugin_platform_interface-2.1.8", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "pool", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pool-1.5.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pool-1.5.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "posix", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/posix-6.5.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/posix-6.5.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "pub_semver", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pub_semver-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pub_semver-2.2.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "pubspec_parse", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_parse-1.5.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pubspec_parse-1.5.0", "packageUri": "lib/", "languageVersion": "3.6" }, { "name": "riverpod", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/riverpod-3.2.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/riverpod-3.2.1", "packageUri": "lib/", "languageVersion": "3.7" }, @@ -561,181 +561,181 @@ }, { "name": "shared_preferences", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences-2.5.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences-2.5.4", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "shared_preferences_android", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_android-2.4.20", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.20", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "shared_preferences_foundation", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_foundation-2.5.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.6", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "shared_preferences_linux", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_linux-2.4.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "shared_preferences_platform_interface", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "shared_preferences_web", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_web-2.4.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "shared_preferences_windows", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_windows-2.4.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "shelf", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf-1.4.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf-1.4.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "shelf_packages_handler", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_packages_handler-3.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf_packages_handler-3.0.2", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "shelf_static", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_static-1.1.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf_static-1.1.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "shelf_web_socket", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_web_socket-3.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf_web_socket-3.0.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "sky_engine", - "rootUri": "file:///C:/Program%20Files/Flutter/bin/cache/pkg/sky_engine", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/bin/cache/pkg/sky_engine", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "source_gen", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_gen-4.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_gen-4.0.0", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "source_helper", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_helper-1.3.8", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_helper-1.3.8", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "source_map_stack_trace", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_map_stack_trace-2.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_map_stack_trace-2.1.2", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "source_maps", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_maps-0.10.13", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_maps-0.10.13", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "source_span", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_span-1.10.2", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "stack_trace", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stack_trace-1.12.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "state_notifier", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/state_notifier-1.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/state_notifier-1.0.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "stream_channel", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stream_channel-2.1.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stream_channel-2.1.4", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "stream_transform", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stream_transform-2.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stream_transform-2.1.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "string_scanner", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.4.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/string_scanner-1.4.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "term_glyph", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/term_glyph-1.2.2", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "test", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/test-1.26.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/test-1.26.2", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "test_api", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/test_api-0.7.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/test_api-0.7.6", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "test_core", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/test_core-0.6.11", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/test_core-0.6.11", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "timing", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/timing-1.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/timing-1.0.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "top_snackbar_flutter", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/top_snackbar_flutter-3.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/top_snackbar_flutter-3.3.0", "packageUri": "lib/", "languageVersion": "2.15" }, { "name": "typed_data", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/typed_data-1.4.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/typed_data-1.4.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "universal_io", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/universal_io-2.3.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/universal_io-2.3.1", "packageUri": "lib/", "languageVersion": "3.6" }, @@ -747,79 +747,79 @@ }, { "name": "vector_graphics", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics-1.1.19", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_graphics-1.1.19", "packageUri": "lib/", "languageVersion": "3.6" }, { "name": "vector_graphics_codec", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics_codec-1.1.13", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.13", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "vector_graphics_compiler", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics_compiler-1.1.20", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.20", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "vector_math", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_math-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_math-2.2.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "vm_service", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vm_service-15.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vm_service-15.0.2", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "watcher", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/watcher-1.2.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/watcher-1.2.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "web", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web-1.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web-1.1.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "web_socket", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket-1.0.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web_socket-1.0.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "web_socket_channel", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket_channel-3.0.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web_socket_channel-3.0.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "webkit_inspection_protocol", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/webkit_inspection_protocol-1.2.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/webkit_inspection_protocol-1.2.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "xdg_directories", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/xdg_directories-1.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "xml", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/xml-6.6.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/xml-6.6.1", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "yaml", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/yaml-3.1.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/yaml-3.1.3", "packageUri": "lib/", "languageVersion": "3.4" }, @@ -832,7 +832,7 @@ ], "generator": "pub", "generatorVersion": "3.9.2", - "flutterRoot": "file:///C:/Program%20Files/Flutter", - "flutterVersion": "3.35.6", - "pubCache": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache" + "flutterRoot": "file:///Users/juliandalcalaf/Development/flutter", + "flutterVersion": "3.35.7", + "pubCache": "file:///Users/juliandalcalaf/.pub-cache" } diff --git a/modules/activity/.dart_tool/version b/modules/activity/.dart_tool/version index eb4861ac..e119acda 100644 --- a/modules/activity/.dart_tool/version +++ b/modules/activity/.dart_tool/version @@ -1 +1 @@ -3.35.6 \ No newline at end of file +3.35.7 \ No newline at end of file diff --git a/modules/activity/.flutter-plugins-dependencies b/modules/activity/.flutter-plugins-dependencies index 48671124..fd7257d2 100644 --- a/modules/activity/.flutter-plugins-dependencies +++ b/modules/activity/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"C:\\\\dev\\\\sf-app-platform\\\\packages\\\\flutter_treezor_entrust_sdk_bridge\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.5.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"C:\\\\dev\\\\sf-app-platform\\\\packages\\\\flutter_treezor_entrust_sdk_bridge\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.2.22\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_android-2.4.20\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.5.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.2.1\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_linux-2.4.1\\\\","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.3.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_windows-2.4.1\\\\","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false}],"web":[{"name":"shared_preferences_web","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_web-2.4.3\\\\","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"flutter_treezor_entrust_sdk_bridge","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]}],"date_created":"2026-03-09 10:57:00.990731","version":"3.35.6","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"/Users/juliandalcalaf/Desktop/apps/sf-app-platform/packages/flutter_treezor_entrust_sdk_bridge/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_foundation-2.5.1/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.6/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"/Users/juliandalcalaf/Desktop/apps/sf-app-platform/packages/flutter_treezor_entrust_sdk_bridge/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_android-2.2.22/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.20/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"path_provider_foundation","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_foundation-2.5.1/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.6/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"path_provider_linux","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false}],"windows":[{"name":"path_provider_windows","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false}],"web":[{"name":"shared_preferences_web","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"flutter_treezor_entrust_sdk_bridge","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]}],"date_created":"2026-03-13 09:49:15.619720","version":"3.35.7","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file diff --git a/modules/activity/devtools_options.yaml b/modules/activity/devtools_options.yaml new file mode 100644 index 00000000..fa0b357c --- /dev/null +++ b/modules/activity/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/modules/auth/lib/src/features/onboarding/presentation/onboarding_screen.dart b/modules/auth/lib/src/features/onboarding/presentation/onboarding_screen.dart index 770aabe3..904c7610 100644 --- a/modules/auth/lib/src/features/onboarding/presentation/onboarding_screen.dart +++ b/modules/auth/lib/src/features/onboarding/presentation/onboarding_screen.dart @@ -32,7 +32,7 @@ class OnboardingScreen extends ConsumerWidget { void goToNext() { if (isLast) { - navigationContract.goTo(AppRoutes.login); + navigationContract.goTo(AppRoutes.legacyLogin); } else { pageController.nextPage( duration: const Duration(milliseconds: 400), @@ -111,7 +111,7 @@ class OnboardingScreen extends ConsumerWidget { ? const SizedBox.shrink() : TextButton( onPressed: () => - navigationContract.goTo(AppRoutes.login), + navigationContract.goTo(AppRoutes.legacyLogin), child: Text( context.translate(I18n.skip), style: AppFonts.stolzlStyle( diff --git a/modules/dashboard_shell/devtools_options.yaml b/modules/dashboard_shell/devtools_options.yaml new file mode 100644 index 00000000..fa0b357c --- /dev/null +++ b/modules/dashboard_shell/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/modules/legacy/modules/account/lib/src/core/data/datasource/users_remote_datasource_impl.dart b/modules/legacy/modules/account/lib/src/core/data/datasource/users_remote_datasource_impl.dart index 15083df7..b95245a4 100644 --- a/modules/legacy/modules/account/lib/src/core/data/datasource/users_remote_datasource_impl.dart +++ b/modules/legacy/modules/account/lib/src/core/data/datasource/users_remote_datasource_impl.dart @@ -16,11 +16,11 @@ class UsersRemoteDatasourceImpl implements UsersRemoteDatasource { Future> getUsers({required String userId}) async { try { final response = await _repository.get>( - '/$userId/devices', + '/users/$userId/user-devices', ); final data = response.data!['items']; if (data == null || data.isEmpty) { - throw Exception('Empty response from /:userId/devices'); + throw Exception('Empty response from /users/$userId/user-devices'); } final model = GetAppUsersResponseModel.fromJson(data); diff --git a/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.dart b/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.dart index 8a27e1e0..06c9ad5b 100644 --- a/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.dart +++ b/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.dart @@ -7,9 +7,6 @@ part 'update_user_request_model.g.dart'; @freezed abstract class UpdateUserRequestModel with _$UpdateUserRequestModel { const factory UpdateUserRequestModel({ - required String id, - String? email, - String? language, String? firstName, String? lastName, String? phone, @@ -21,9 +18,6 @@ abstract class UpdateUserRequestModel with _$UpdateUserRequestModel { extension UpdateUserRequestModelMapper on UpdateUserRequestEntity { UpdateUserRequestModel toModel() => UpdateUserRequestModel( - id: id, - email: email, - language: language, firstName: firstName, lastName: lastName, phone: phone, diff --git a/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.freezed.dart b/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.freezed.dart index ecb9ef2d..adaaed0d 100644 --- a/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.freezed.dart +++ b/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.freezed.dart @@ -15,7 +15,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$UpdateUserRequestModel { - String get id; String? get email; String? get language; String? get firstName; String? get lastName; String? get phone; + String? get firstName; String? get lastName; String? get phone; /// Create a copy of UpdateUserRequestModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -28,16 +28,16 @@ $UpdateUserRequestModelCopyWith get copyWith => _$Update @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is UpdateUserRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.email, email) || other.email == email)&&(identical(other.language, language) || other.language == language)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.phone, phone) || other.phone == phone)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is UpdateUserRequestModel&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.phone, phone) || other.phone == phone)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,id,email,language,firstName,lastName,phone); +int get hashCode => Object.hash(runtimeType,firstName,lastName,phone); @override String toString() { - return 'UpdateUserRequestModel(id: $id, email: $email, language: $language, firstName: $firstName, lastName: $lastName, phone: $phone)'; + return 'UpdateUserRequestModel(firstName: $firstName, lastName: $lastName, phone: $phone)'; } @@ -48,7 +48,7 @@ abstract mixin class $UpdateUserRequestModelCopyWith<$Res> { factory $UpdateUserRequestModelCopyWith(UpdateUserRequestModel value, $Res Function(UpdateUserRequestModel) _then) = _$UpdateUserRequestModelCopyWithImpl; @useResult $Res call({ - String id, String? email, String? language, String? firstName, String? lastName, String? phone + String? firstName, String? lastName, String? phone }); @@ -65,12 +65,9 @@ class _$UpdateUserRequestModelCopyWithImpl<$Res> /// Create a copy of UpdateUserRequestModel /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? email = freezed,Object? language = freezed,Object? firstName = freezed,Object? lastName = freezed,Object? phone = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? firstName = freezed,Object? lastName = freezed,Object? phone = freezed,}) { return _then(_self.copyWith( -id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String,email: freezed == email ? _self.email : email // ignore: cast_nullable_to_non_nullable -as String?,language: freezed == language ? _self.language : language // ignore: cast_nullable_to_non_nullable -as String?,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable +firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable as String?,phone: freezed == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable as String?, @@ -158,10 +155,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String? email, String? language, String? firstName, String? lastName, String? phone)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String? firstName, String? lastName, String? phone)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _UpdateUserRequestModel() when $default != null: -return $default(_that.id,_that.email,_that.language,_that.firstName,_that.lastName,_that.phone);case _: +return $default(_that.firstName,_that.lastName,_that.phone);case _: return orElse(); } @@ -179,10 +176,10 @@ return $default(_that.id,_that.email,_that.language,_that.firstName,_that.lastNa /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String id, String? email, String? language, String? firstName, String? lastName, String? phone) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String? firstName, String? lastName, String? phone) $default,) {final _that = this; switch (_that) { case _UpdateUserRequestModel(): -return $default(_that.id,_that.email,_that.language,_that.firstName,_that.lastName,_that.phone);case _: +return $default(_that.firstName,_that.lastName,_that.phone);case _: throw StateError('Unexpected subclass'); } @@ -199,10 +196,10 @@ return $default(_that.id,_that.email,_that.language,_that.firstName,_that.lastNa /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String? email, String? language, String? firstName, String? lastName, String? phone)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String? firstName, String? lastName, String? phone)? $default,) {final _that = this; switch (_that) { case _UpdateUserRequestModel() when $default != null: -return $default(_that.id,_that.email,_that.language,_that.firstName,_that.lastName,_that.phone);case _: +return $default(_that.firstName,_that.lastName,_that.phone);case _: return null; } @@ -214,12 +211,9 @@ return $default(_that.id,_that.email,_that.language,_that.firstName,_that.lastNa @JsonSerializable() class _UpdateUserRequestModel implements UpdateUserRequestModel { - const _UpdateUserRequestModel({required this.id, this.email, this.language, this.firstName, this.lastName, this.phone}); + const _UpdateUserRequestModel({this.firstName, this.lastName, this.phone}); factory _UpdateUserRequestModel.fromJson(Map json) => _$UpdateUserRequestModelFromJson(json); -@override final String id; -@override final String? email; -@override final String? language; @override final String? firstName; @override final String? lastName; @override final String? phone; @@ -237,16 +231,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _UpdateUserRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.email, email) || other.email == email)&&(identical(other.language, language) || other.language == language)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.phone, phone) || other.phone == phone)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _UpdateUserRequestModel&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.phone, phone) || other.phone == phone)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,id,email,language,firstName,lastName,phone); +int get hashCode => Object.hash(runtimeType,firstName,lastName,phone); @override String toString() { - return 'UpdateUserRequestModel(id: $id, email: $email, language: $language, firstName: $firstName, lastName: $lastName, phone: $phone)'; + return 'UpdateUserRequestModel(firstName: $firstName, lastName: $lastName, phone: $phone)'; } @@ -257,7 +251,7 @@ abstract mixin class _$UpdateUserRequestModelCopyWith<$Res> implements $UpdateUs factory _$UpdateUserRequestModelCopyWith(_UpdateUserRequestModel value, $Res Function(_UpdateUserRequestModel) _then) = __$UpdateUserRequestModelCopyWithImpl; @override @useResult $Res call({ - String id, String? email, String? language, String? firstName, String? lastName, String? phone + String? firstName, String? lastName, String? phone }); @@ -274,12 +268,9 @@ class __$UpdateUserRequestModelCopyWithImpl<$Res> /// Create a copy of UpdateUserRequestModel /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? email = freezed,Object? language = freezed,Object? firstName = freezed,Object? lastName = freezed,Object? phone = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? firstName = freezed,Object? lastName = freezed,Object? phone = freezed,}) { return _then(_UpdateUserRequestModel( -id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String,email: freezed == email ? _self.email : email // ignore: cast_nullable_to_non_nullable -as String?,language: freezed == language ? _self.language : language // ignore: cast_nullable_to_non_nullable -as String?,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable +firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable as String?,phone: freezed == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable as String?, diff --git a/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.g.dart b/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.g.dart index 50dce3de..f6f0d948 100644 --- a/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.g.dart +++ b/modules/legacy/modules/account/lib/src/core/data/models/update_user_request_model.g.dart @@ -9,9 +9,6 @@ part of 'update_user_request_model.dart'; _UpdateUserRequestModel _$UpdateUserRequestModelFromJson( Map json, ) => _UpdateUserRequestModel( - id: json['id'] as String, - email: json['email'] as String?, - language: json['language'] as String?, firstName: json['firstName'] as String?, lastName: json['lastName'] as String?, phone: json['phone'] as String?, @@ -20,9 +17,6 @@ _UpdateUserRequestModel _$UpdateUserRequestModelFromJson( Map _$UpdateUserRequestModelToJson( _UpdateUserRequestModel instance, ) => { - 'id': instance.id, - 'email': instance.email, - 'language': instance.language, 'firstName': instance.firstName, 'lastName': instance.lastName, 'phone': instance.phone, diff --git a/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart index e5011837..ac092bf6 100644 --- a/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart @@ -1,7 +1,7 @@ +import 'package:account/src/features/account_settings/presentation/state/account_settings_view_model.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:legacy_auth/legacy_auth.dart'; import 'package:legacy_shared/legacy_shared.dart'; import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; @@ -12,163 +12,131 @@ import 'widgets/reg_code_dialog.dart'; class AccountSettingsScreen extends ConsumerWidget { final NavigationContract navigationContract; - static final _privacyUrl = 'https://savefamilygps.com/pages/politica-de-privacidad-reloj-gps-infantil-localizador-savefamily'; + static final _privacyUrl = + 'https://savefamilygps.com/pages/politica-de-privacidad-reloj-gps-infantil-localizador-savefamily'; const AccountSettingsScreen({super.key, required this.navigationContract}); @override Widget build(BuildContext context, WidgetRef ref) { final theme = ref.watch(themePortProvider); - + final color = theme.getColorFor(ThemeCode.legacyPrimary); final selectedDevice = ref.watch(selectedDeviceProvider); + final isLoggingOut = ref.watch( + accountSettingsViewModelProvider.select((s) => s.isLoggingOut), + ); + + ref.listen( + accountSettingsViewModelProvider.select((s) => s.isLoggingOut), + (prev, isLoggingOut) { + if (prev == true && !isLoggingOut) { + navigationContract.goTo(AppRoutes.legacyLogin); + } + }, + ); return LegacyPageLayout( theme: theme, title: context.translate(I18n.accountSettings), - body: SingleChildScrollView(child: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 8) - ), - child: Column( - children: [ - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.personalData);}, - icon: SFIcons.account, - text: I18n.personalData - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.changePassword);}, - icon: Icons.lock, - text: I18n.changePassword - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => LegacyDeviceSetupScreen( - navigationContract: navigationContract, - isFirstDevice: false + body: SingleChildScrollView( + child: Padding( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), + big: EdgeInsets.symmetric(horizontal: 21, vertical: 8), + ), + child: Column( + children: [ + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.personalData), icon: SFIcons.account, text: I18n.personalData, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.changePassword), icon: Icons.lock, text: I18n.changePassword, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.legacyDeviceSetup), icon: Icons.add_circle_outline, text: I18n.addNewSF, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.linkedDevices), icon: Icons.account_circle_outlined, text: I18n.linkedDevices, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.appUsers), icon: Icons.groups_outlined, text: I18n.appUsers, color: color), + _item( + context, + onPressed: () async { + final Uri url = Uri.parse(_privacyUrl); + if (!await launchUrl(url)) { + throw Exception('Could not launch $url'); + } + }, + icon: SFIcons.privacy, + text: I18n.privacyPolicy, + color: color, + ), + _item( + context, + onPressed: () { + showDialog( + context: context, + builder: (context) => Dialog( + backgroundColor: Colors.transparent, + child: RegCodeDialog( + regCode: selectedDevice?.id ?? '', + deviceId: selectedDevice?.identificator ?? '', + name: selectedDevice?.carrierName ?? '', + ), ), - ), - ); - }, - icon: Icons.add_circle_outline, - text: I18n.addNewSF - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.linkedDevices);}, - icon: Icons.account_circle_outlined, - text: I18n.linkedDevices - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.appUsers);}, - icon: Icons.groups_outlined, - text: I18n.appUsers - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: () async { - final Uri url = Uri.parse(_privacyUrl); - if (!await launchUrl(url)) { - throw Exception('Could not launch $url'); - } - }, - icon: SFIcons.privacy, - text: I18n.privacyPolicy - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){ - showDialog(context: context, builder: (context)=>Dialog( - backgroundColor: Colors.transparent, - child: RegCodeDialog( - regCode: selectedDevice?.id ?? '', - deviceId: selectedDevice?.identificator ?? '', - name: selectedDevice?.carrierName ?? '' - ), - )); - }, - icon: Icons.qr_code, - text: I18n.regCode - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.deleteAccount);}, - icon: Icons.no_accounts, - text: I18n.deleteAccount - ), - ], + ); + }, + icon: Icons.qr_code, + text: I18n.regCode, + color: color, + ), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.deleteAccount), icon: Icons.no_accounts, text: I18n.deleteAccount, color: color), + ], + ), ), - )), + ), footer: Container( padding: SizeUtils.getByScreen( small: EdgeInsets.symmetric(vertical: 12, horizontal: 30), - big: EdgeInsets.symmetric(vertical: 10, horizontal: 28) + big: EdgeInsets.symmetric(vertical: 10, horizontal: 28), ), - child: PrimaryButton(text: context.translate(I18n.logOut), color: theme.getColorFor(ThemeCode.legacyPrimary)), - ) + child: PrimaryButton( + text: context.translate(I18n.logOut), + color: theme.getColorFor(ThemeCode.legacyPrimary), + leading: isLoggingOut + ? const SizedBox( + height: 18, + width: 18, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.white, + ), + ) + : null, + onPressed: isLoggingOut + ? () {} + : ref.read(accountSettingsViewModelProvider.notifier).logout, + ), + ), + ); + } + + Widget _item( + BuildContext context, { + required VoidCallback onPressed, + required IconData icon, + required String text, + required Color color, + }) { + return Padding( + padding: EdgeInsets.only(bottom: SizeUtils.getByScreen(small: 16, big: 15)), + child: SectionButton( + onPressed: onPressed, + icon: Icon( + icon, + size: SizeUtils.getByScreen(small: 28, big: 26), + color: color, + ), + body: Text( + context.translate(text), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 18, big: 19), + fontWeight: FontWeight.w500, + ), + ), + ), ); } } - -class AppSectionButton extends ConsumerWidget { - - final GestureTapCallback onPressed; - final IconData icon; - final String text; - - const AppSectionButton({ - required this.onPressed, - required this.icon, - required this.text, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.watch(themePortProvider); - - return GestureDetector( - onTap: onPressed, - child: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 20), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 18) - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(SizeUtils.getByScreen(small: 12, big: 18))), - color: theme.getColorFor(ThemeCode.backgroundSecondary), - ), - child: Row( - children: [ - Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: theme.getColorFor(ThemeCode.backgroundPrimary), - ), - padding: EdgeInsets.all(SizeUtils.getByScreen(small: 4, big: 12)), - child: Icon(icon, - size: SizeUtils.getByScreen(small: 40, big: 44), - color: theme.getColorFor(ThemeCode.legacyPrimary), - weight: 30, - ), - ), - SizedBox(width: SizeUtils.getByScreen(small: 16, big: 15)), - Expanded( - child: Text(context.translate(text), - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 18, big: 19), - fontWeight: FontWeight.w500 - ) - ) - ) - ], - ), - ) - ); - } -} \ No newline at end of file diff --git a/modules/legacy/modules/account/lib/src/features/account_settings/presentation/state/account_settings_view_model.dart b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/state/account_settings_view_model.dart new file mode 100644 index 00000000..275bc9f0 --- /dev/null +++ b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/state/account_settings_view_model.dart @@ -0,0 +1,30 @@ +import 'package:account/src/features/account_settings/presentation/state/account_settings_view_state.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_auth/legacy_auth.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +final accountSettingsViewModelProvider = + NotifierProvider.autoDispose( + AccountSettingsViewModel.new, + ); + +class AccountSettingsViewModel extends Notifier { + @override + AccountSettingsViewState build() { + return const AccountSettingsViewState(); + } + + Future logout() async { + if (state.isLoggingOut) return; + + state = state.copyWith(isLoggingOut: true, errorMessage: ''); + + try { + await ref.read(legacyAuthRepositoryProvider).logout(); + } catch (_) {} + + await clearSessionData(); + + state = state.copyWith(isLoggingOut: false); + } +} diff --git a/modules/legacy/modules/account/lib/src/features/account_settings/presentation/state/account_settings_view_state.dart b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/state/account_settings_view_state.dart new file mode 100644 index 00000000..cf7b60df --- /dev/null +++ b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/state/account_settings_view_state.dart @@ -0,0 +1,11 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'account_settings_view_state.freezed.dart'; + +@freezed +abstract class AccountSettingsViewState with _$AccountSettingsViewState { + const factory AccountSettingsViewState({ + @Default(false) bool isLoggingOut, + @Default('') String errorMessage, + }) = _AccountSettingsViewState; +} diff --git a/modules/legacy/modules/account/lib/src/features/account_settings/presentation/state/account_settings_view_state.freezed.dart b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/state/account_settings_view_state.freezed.dart new file mode 100644 index 00000000..611e444c --- /dev/null +++ b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/state/account_settings_view_state.freezed.dart @@ -0,0 +1,274 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'account_settings_view_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$AccountSettingsViewState { + + bool get isLoggingOut; String get errorMessage; +/// Create a copy of AccountSettingsViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AccountSettingsViewStateCopyWith get copyWith => _$AccountSettingsViewStateCopyWithImpl(this as AccountSettingsViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AccountSettingsViewState&&(identical(other.isLoggingOut, isLoggingOut) || other.isLoggingOut == isLoggingOut)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,isLoggingOut,errorMessage); + +@override +String toString() { + return 'AccountSettingsViewState(isLoggingOut: $isLoggingOut, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class $AccountSettingsViewStateCopyWith<$Res> { + factory $AccountSettingsViewStateCopyWith(AccountSettingsViewState value, $Res Function(AccountSettingsViewState) _then) = _$AccountSettingsViewStateCopyWithImpl; +@useResult +$Res call({ + bool isLoggingOut, String errorMessage +}); + + + + +} +/// @nodoc +class _$AccountSettingsViewStateCopyWithImpl<$Res> + implements $AccountSettingsViewStateCopyWith<$Res> { + _$AccountSettingsViewStateCopyWithImpl(this._self, this._then); + + final AccountSettingsViewState _self; + final $Res Function(AccountSettingsViewState) _then; + +/// Create a copy of AccountSettingsViewState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? isLoggingOut = null,Object? errorMessage = null,}) { + return _then(_self.copyWith( +isLoggingOut: null == isLoggingOut ? _self.isLoggingOut : isLoggingOut // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [AccountSettingsViewState]. +extension AccountSettingsViewStatePatterns on AccountSettingsViewState { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AccountSettingsViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AccountSettingsViewState() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AccountSettingsViewState value) $default,){ +final _that = this; +switch (_that) { +case _AccountSettingsViewState(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AccountSettingsViewState value)? $default,){ +final _that = this; +switch (_that) { +case _AccountSettingsViewState() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( bool isLoggingOut, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AccountSettingsViewState() when $default != null: +return $default(_that.isLoggingOut,_that.errorMessage);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( bool isLoggingOut, String errorMessage) $default,) {final _that = this; +switch (_that) { +case _AccountSettingsViewState(): +return $default(_that.isLoggingOut,_that.errorMessage);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool isLoggingOut, String errorMessage)? $default,) {final _that = this; +switch (_that) { +case _AccountSettingsViewState() when $default != null: +return $default(_that.isLoggingOut,_that.errorMessage);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _AccountSettingsViewState implements AccountSettingsViewState { + const _AccountSettingsViewState({this.isLoggingOut = false, this.errorMessage = ''}); + + +@override@JsonKey() final bool isLoggingOut; +@override@JsonKey() final String errorMessage; + +/// Create a copy of AccountSettingsViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AccountSettingsViewStateCopyWith<_AccountSettingsViewState> get copyWith => __$AccountSettingsViewStateCopyWithImpl<_AccountSettingsViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AccountSettingsViewState&&(identical(other.isLoggingOut, isLoggingOut) || other.isLoggingOut == isLoggingOut)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,isLoggingOut,errorMessage); + +@override +String toString() { + return 'AccountSettingsViewState(isLoggingOut: $isLoggingOut, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class _$AccountSettingsViewStateCopyWith<$Res> implements $AccountSettingsViewStateCopyWith<$Res> { + factory _$AccountSettingsViewStateCopyWith(_AccountSettingsViewState value, $Res Function(_AccountSettingsViewState) _then) = __$AccountSettingsViewStateCopyWithImpl; +@override @useResult +$Res call({ + bool isLoggingOut, String errorMessage +}); + + + + +} +/// @nodoc +class __$AccountSettingsViewStateCopyWithImpl<$Res> + implements _$AccountSettingsViewStateCopyWith<$Res> { + __$AccountSettingsViewStateCopyWithImpl(this._self, this._then); + + final _AccountSettingsViewState _self; + final $Res Function(_AccountSettingsViewState) _then; + +/// Create a copy of AccountSettingsViewState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? isLoggingOut = null,Object? errorMessage = null,}) { + return _then(_AccountSettingsViewState( +isLoggingOut: null == isLoggingOut ? _self.isLoggingOut : isLoggingOut // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/account/lib/src/features/account_settings/presentation/widgets/reg_code_dialog.dart b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/widgets/reg_code_dialog.dart index 7be1f29e..52e3b6c3 100644 --- a/modules/legacy/modules/account/lib/src/features/account_settings/presentation/widgets/reg_code_dialog.dart +++ b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/widgets/reg_code_dialog.dart @@ -6,7 +6,6 @@ import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; class RegCodeDialog extends StatelessWidget { - final String regCode; final String deviceId; final String name; @@ -18,87 +17,118 @@ class RegCodeDialog extends StatelessWidget { required this.name, }); + static const _iconRadius = 40.0; + @override Widget build(BuildContext context) { - return Container( - height: SizeUtils.getByScreen(small: 330, big: 328), - color: Colors.transparent, - child: Stack( - children: [ - Align( - alignment: Alignment.bottomCenter, - child: Container( - height: SizeUtils.getByScreen(small: 300, big: 298), - width: SizeUtils.getByScreen(small: 350, big: 348), - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(vertical: 14, horizontal: 18), - big: EdgeInsets.symmetric(vertical: 12, horizontal: 16) + return Stack( + clipBehavior: Clip.none, + alignment: Alignment.topCenter, + children: [ + Container( + width: SizeUtils.getByScreen(small: 320, big: 340), + margin: const EdgeInsets.only(top: _iconRadius), + padding: EdgeInsets.only( + top: _iconRadius + SizeUtils.getByScreen(small: 12, big: 10), + bottom: SizeUtils.getByScreen(small: 20, big: 18), + left: SizeUtils.getByScreen(small: 20, big: 18), + right: SizeUtils.getByScreen(small: 20, big: 18), + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Align( + alignment: Alignment.topRight, + child: GestureDetector( + onTap: () => Navigator.pop(context), + child: const Icon(Icons.close, size: 22, color: Colors.grey), + ), ), - color: Colors.white, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: (){Navigator.pop(context);}, - icon: Icon(Icons.close), - padding: EdgeInsets.zero, - ), - ), - Text(name, style: TextStyle()), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(context.translate(I18n.deviceIdLabel, - args: {'deviceId': deviceId})), - TextButton( - onPressed: (){Clipboard.setData(ClipboardData(text: deviceId));}, - child: Text(context.translate(I18n.copy)), - ) - ], - ), - QrImageView( - data: regCode, - version: QrVersions.auto, - size: SizeUtils.getByScreen(small: 100, big: 98), - padding: EdgeInsets.zero, - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(context.translate(I18n.regCodeLabel, - args: {'regCode': regCode})), - TextButton( - onPressed: (){Clipboard.setData(ClipboardData(text: regCode));}, - child: Text(context.translate(I18n.copy)) - ) - ], - ) - ], + Text( + name, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 16), + _CopyableField( + label: context.translate( + I18n.deviceIdLabel, + args: {'deviceId': deviceId}, + ), + value: deviceId, + ), + const SizedBox(height: 20), + QrImageView( + data: regCode, + version: QrVersions.auto, + size: SizeUtils.getByScreen(small: 120, big: 120), + padding: EdgeInsets.zero, + ), + const SizedBox(height: 16), + _CopyableField( + label: context.translate( + I18n.regCodeLabel, + args: {'regCode': regCode}, + ), + value: regCode, + ), + ], + ), + ), + Container( + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: Color(0xFF00A1C6), + ), + padding: EdgeInsets.all(SizeUtils.getByScreen(small: 16, big: 16)), + child: Icon( + SFIcons.watch, + size: SizeUtils.getByScreen(small: 68, big: 66), + color: Colors.white, + ), + ), + ], + ); + } +} + +class _CopyableField extends StatelessWidget { + final String label; + final String value; + + const _CopyableField({required this.label, required this.value}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => Clipboard.setData(ClipboardData(text: value)), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), + decoration: BoxDecoration( + color: Colors.grey.withValues(alpha: 0.08), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Text( + label, + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 13), ), ), - ), - Align( - alignment: Alignment.topCenter, - child: Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Color(0xFF00A1C6), - ), - padding: SizeUtils.getByScreen( - small: EdgeInsets.all(12), - big: EdgeInsets.all(12) - ), - child: Icon( - SFIcons.watch, - size: SizeUtils.getByScreen(small: 68, big: 66), - color: Colors.white, - ), - ) - ), - ], + const SizedBox(width: 6), + const Icon(Icons.copy, size: 14, color: Colors.grey), + ], + ), ), ); } -} \ No newline at end of file +} diff --git a/modules/legacy/modules/account/lib/src/features/change_password/presentation/state/change_password_view_model.dart b/modules/legacy/modules/account/lib/src/features/change_password/presentation/state/change_password_view_model.dart index f5757787..e5a86e94 100644 --- a/modules/legacy/modules/account/lib/src/features/change_password/presentation/state/change_password_view_model.dart +++ b/modules/legacy/modules/account/lib/src/features/change_password/presentation/state/change_password_view_model.dart @@ -139,7 +139,6 @@ class ChangePasswordViewModel extends Notifier { isLoading: false, isComplete: true ); - ref.invalidate(userInfoProvider); } catch (e) { if (!ref.mounted) return; _finishWithError(message: e.toString()); diff --git a/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_model.dart b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_model.dart index a8017a8c..c633e262 100644 --- a/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_model.dart +++ b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_model.dart @@ -19,6 +19,7 @@ class DeleteAccountViewModel extends Notifier { @override DeleteAccountViewState build() { _usersRepository = ref.read(usersRepositoryProvider); + _devicesRepository = ref.read(sharedDevicesRepositoryProvider); passwordController = TextEditingController(); passwordController.addListener(_onPasswordChanged); @@ -104,8 +105,6 @@ class DeleteAccountViewModel extends Notifier { await _usersRepository.deleteUser(userId: state.loggedUser!.id); if (!ref.mounted) return; - ref.invalidate(userInfoProvider); - state = state.copyWith( isLoading: false, isComplete: true diff --git a/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/edit_linked_device_screen.dart b/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/edit_linked_device_screen.dart index 7b0b8bbe..4ffd8274 100644 --- a/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/edit_linked_device_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/edit_linked_device_screen.dart @@ -42,7 +42,7 @@ class EditLinkedDeviceScreen extends ConsumerWidget { Stack( children: [ DecoratedBox(decoration: BoxDecoration(color: Colors.blueAccent)), - Center(child: SvgPicture.asset('assets/images/ui/profile.svg')), + Center(child: SvgPicture.asset('assets/shared/images/profile.svg')), Center(child: SizedBox( width: 160, height: 160, diff --git a/modules/legacy/modules/account/lib/src/features/personal_data/domain/entities/update_user_request_entity.dart b/modules/legacy/modules/account/lib/src/features/personal_data/domain/entities/update_user_request_entity.dart index d172b542..91967276 100644 --- a/modules/legacy/modules/account/lib/src/features/personal_data/domain/entities/update_user_request_entity.dart +++ b/modules/legacy/modules/account/lib/src/features/personal_data/domain/entities/update_user_request_entity.dart @@ -5,19 +5,8 @@ part 'update_user_request_entity.freezed.dart'; @freezed abstract class UpdateUserRequestEntity with _$UpdateUserRequestEntity { const factory UpdateUserRequestEntity({ - required String id, - String? delegationId, - String? email, - String? createdAt, - String? updatedAt, - String? status, - String? role, - String? lastLogin, - String? currentLogin, - String? language, - String? firstName, - String? lastName, - String? hasApiKey, - String? phone, + String? firstName, + String? lastName, + String? phone, }) = _UpdateUserRequestEntity; } diff --git a/modules/legacy/modules/account/lib/src/features/personal_data/domain/entities/update_user_request_entity.freezed.dart b/modules/legacy/modules/account/lib/src/features/personal_data/domain/entities/update_user_request_entity.freezed.dart index 74e60adc..1480ba6a 100644 --- a/modules/legacy/modules/account/lib/src/features/personal_data/domain/entities/update_user_request_entity.freezed.dart +++ b/modules/legacy/modules/account/lib/src/features/personal_data/domain/entities/update_user_request_entity.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$UpdateUserRequestEntity { - String get id; String? get delegationId; String? get email; String? get createdAt; String? get updatedAt; String? get status; String? get role; String? get lastLogin; String? get currentLogin; String? get language; String? get firstName; String? get lastName; String? get hasApiKey; String? get phone; + String? get firstName; String? get lastName; String? get phone; /// Create a copy of UpdateUserRequestEntity /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $UpdateUserRequestEntityCopyWith get copyWith => _$Upda @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is UpdateUserRequestEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.delegationId, delegationId) || other.delegationId == delegationId)&&(identical(other.email, email) || other.email == email)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.status, status) || other.status == status)&&(identical(other.role, role) || other.role == role)&&(identical(other.lastLogin, lastLogin) || other.lastLogin == lastLogin)&&(identical(other.currentLogin, currentLogin) || other.currentLogin == currentLogin)&&(identical(other.language, language) || other.language == language)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.hasApiKey, hasApiKey) || other.hasApiKey == hasApiKey)&&(identical(other.phone, phone) || other.phone == phone)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is UpdateUserRequestEntity&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.phone, phone) || other.phone == phone)); } @override -int get hashCode => Object.hash(runtimeType,id,delegationId,email,createdAt,updatedAt,status,role,lastLogin,currentLogin,language,firstName,lastName,hasApiKey,phone); +int get hashCode => Object.hash(runtimeType,firstName,lastName,phone); @override String toString() { - return 'UpdateUserRequestEntity(id: $id, delegationId: $delegationId, email: $email, createdAt: $createdAt, updatedAt: $updatedAt, status: $status, role: $role, lastLogin: $lastLogin, currentLogin: $currentLogin, language: $language, firstName: $firstName, lastName: $lastName, hasApiKey: $hasApiKey, phone: $phone)'; + return 'UpdateUserRequestEntity(firstName: $firstName, lastName: $lastName, phone: $phone)'; } @@ -45,7 +45,7 @@ abstract mixin class $UpdateUserRequestEntityCopyWith<$Res> { factory $UpdateUserRequestEntityCopyWith(UpdateUserRequestEntity value, $Res Function(UpdateUserRequestEntity) _then) = _$UpdateUserRequestEntityCopyWithImpl; @useResult $Res call({ - String id, String? delegationId, String? email, String? createdAt, String? updatedAt, String? status, String? role, String? lastLogin, String? currentLogin, String? language, String? firstName, String? lastName, String? hasApiKey, String? phone + String? firstName, String? lastName, String? phone }); @@ -62,21 +62,10 @@ class _$UpdateUserRequestEntityCopyWithImpl<$Res> /// Create a copy of UpdateUserRequestEntity /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? delegationId = freezed,Object? email = freezed,Object? createdAt = freezed,Object? updatedAt = freezed,Object? status = freezed,Object? role = freezed,Object? lastLogin = freezed,Object? currentLogin = freezed,Object? language = freezed,Object? firstName = freezed,Object? lastName = freezed,Object? hasApiKey = freezed,Object? phone = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? firstName = freezed,Object? lastName = freezed,Object? phone = freezed,}) { return _then(_self.copyWith( -id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String,delegationId: freezed == delegationId ? _self.delegationId : delegationId // ignore: cast_nullable_to_non_nullable -as String?,email: freezed == email ? _self.email : email // ignore: cast_nullable_to_non_nullable -as String?,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable -as String?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable -as String?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable -as String?,role: freezed == role ? _self.role : role // ignore: cast_nullable_to_non_nullable -as String?,lastLogin: freezed == lastLogin ? _self.lastLogin : lastLogin // ignore: cast_nullable_to_non_nullable -as String?,currentLogin: freezed == currentLogin ? _self.currentLogin : currentLogin // ignore: cast_nullable_to_non_nullable -as String?,language: freezed == language ? _self.language : language // ignore: cast_nullable_to_non_nullable -as String?,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable +firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable -as String?,hasApiKey: freezed == hasApiKey ? _self.hasApiKey : hasApiKey // ignore: cast_nullable_to_non_nullable as String?,phone: freezed == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable as String?, )); @@ -163,10 +152,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String? delegationId, String? email, String? createdAt, String? updatedAt, String? status, String? role, String? lastLogin, String? currentLogin, String? language, String? firstName, String? lastName, String? hasApiKey, String? phone)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String? firstName, String? lastName, String? phone)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _UpdateUserRequestEntity() when $default != null: -return $default(_that.id,_that.delegationId,_that.email,_that.createdAt,_that.updatedAt,_that.status,_that.role,_that.lastLogin,_that.currentLogin,_that.language,_that.firstName,_that.lastName,_that.hasApiKey,_that.phone);case _: +return $default(_that.firstName,_that.lastName,_that.phone);case _: return orElse(); } @@ -184,10 +173,10 @@ return $default(_that.id,_that.delegationId,_that.email,_that.createdAt,_that.up /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String id, String? delegationId, String? email, String? createdAt, String? updatedAt, String? status, String? role, String? lastLogin, String? currentLogin, String? language, String? firstName, String? lastName, String? hasApiKey, String? phone) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String? firstName, String? lastName, String? phone) $default,) {final _that = this; switch (_that) { case _UpdateUserRequestEntity(): -return $default(_that.id,_that.delegationId,_that.email,_that.createdAt,_that.updatedAt,_that.status,_that.role,_that.lastLogin,_that.currentLogin,_that.language,_that.firstName,_that.lastName,_that.hasApiKey,_that.phone);case _: +return $default(_that.firstName,_that.lastName,_that.phone);case _: throw StateError('Unexpected subclass'); } @@ -204,10 +193,10 @@ return $default(_that.id,_that.delegationId,_that.email,_that.createdAt,_that.up /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String? delegationId, String? email, String? createdAt, String? updatedAt, String? status, String? role, String? lastLogin, String? currentLogin, String? language, String? firstName, String? lastName, String? hasApiKey, String? phone)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String? firstName, String? lastName, String? phone)? $default,) {final _that = this; switch (_that) { case _UpdateUserRequestEntity() when $default != null: -return $default(_that.id,_that.delegationId,_that.email,_that.createdAt,_that.updatedAt,_that.status,_that.role,_that.lastLogin,_that.currentLogin,_that.language,_that.firstName,_that.lastName,_that.hasApiKey,_that.phone);case _: +return $default(_that.firstName,_that.lastName,_that.phone);case _: return null; } @@ -219,22 +208,11 @@ return $default(_that.id,_that.delegationId,_that.email,_that.createdAt,_that.up class _UpdateUserRequestEntity implements UpdateUserRequestEntity { - const _UpdateUserRequestEntity({required this.id, this.delegationId, this.email, this.createdAt, this.updatedAt, this.status, this.role, this.lastLogin, this.currentLogin, this.language, this.firstName, this.lastName, this.hasApiKey, this.phone}); + const _UpdateUserRequestEntity({this.firstName, this.lastName, this.phone}); -@override final String id; -@override final String? delegationId; -@override final String? email; -@override final String? createdAt; -@override final String? updatedAt; -@override final String? status; -@override final String? role; -@override final String? lastLogin; -@override final String? currentLogin; -@override final String? language; @override final String? firstName; @override final String? lastName; -@override final String? hasApiKey; @override final String? phone; /// Create a copy of UpdateUserRequestEntity @@ -247,16 +225,16 @@ _$UpdateUserRequestEntityCopyWith<_UpdateUserRequestEntity> get copyWith => __$U @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _UpdateUserRequestEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.delegationId, delegationId) || other.delegationId == delegationId)&&(identical(other.email, email) || other.email == email)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.status, status) || other.status == status)&&(identical(other.role, role) || other.role == role)&&(identical(other.lastLogin, lastLogin) || other.lastLogin == lastLogin)&&(identical(other.currentLogin, currentLogin) || other.currentLogin == currentLogin)&&(identical(other.language, language) || other.language == language)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.hasApiKey, hasApiKey) || other.hasApiKey == hasApiKey)&&(identical(other.phone, phone) || other.phone == phone)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _UpdateUserRequestEntity&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.phone, phone) || other.phone == phone)); } @override -int get hashCode => Object.hash(runtimeType,id,delegationId,email,createdAt,updatedAt,status,role,lastLogin,currentLogin,language,firstName,lastName,hasApiKey,phone); +int get hashCode => Object.hash(runtimeType,firstName,lastName,phone); @override String toString() { - return 'UpdateUserRequestEntity(id: $id, delegationId: $delegationId, email: $email, createdAt: $createdAt, updatedAt: $updatedAt, status: $status, role: $role, lastLogin: $lastLogin, currentLogin: $currentLogin, language: $language, firstName: $firstName, lastName: $lastName, hasApiKey: $hasApiKey, phone: $phone)'; + return 'UpdateUserRequestEntity(firstName: $firstName, lastName: $lastName, phone: $phone)'; } @@ -267,7 +245,7 @@ abstract mixin class _$UpdateUserRequestEntityCopyWith<$Res> implements $UpdateU factory _$UpdateUserRequestEntityCopyWith(_UpdateUserRequestEntity value, $Res Function(_UpdateUserRequestEntity) _then) = __$UpdateUserRequestEntityCopyWithImpl; @override @useResult $Res call({ - String id, String? delegationId, String? email, String? createdAt, String? updatedAt, String? status, String? role, String? lastLogin, String? currentLogin, String? language, String? firstName, String? lastName, String? hasApiKey, String? phone + String? firstName, String? lastName, String? phone }); @@ -284,21 +262,10 @@ class __$UpdateUserRequestEntityCopyWithImpl<$Res> /// Create a copy of UpdateUserRequestEntity /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? delegationId = freezed,Object? email = freezed,Object? createdAt = freezed,Object? updatedAt = freezed,Object? status = freezed,Object? role = freezed,Object? lastLogin = freezed,Object? currentLogin = freezed,Object? language = freezed,Object? firstName = freezed,Object? lastName = freezed,Object? hasApiKey = freezed,Object? phone = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? firstName = freezed,Object? lastName = freezed,Object? phone = freezed,}) { return _then(_UpdateUserRequestEntity( -id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String,delegationId: freezed == delegationId ? _self.delegationId : delegationId // ignore: cast_nullable_to_non_nullable -as String?,email: freezed == email ? _self.email : email // ignore: cast_nullable_to_non_nullable -as String?,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable -as String?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable -as String?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable -as String?,role: freezed == role ? _self.role : role // ignore: cast_nullable_to_non_nullable -as String?,lastLogin: freezed == lastLogin ? _self.lastLogin : lastLogin // ignore: cast_nullable_to_non_nullable -as String?,currentLogin: freezed == currentLogin ? _self.currentLogin : currentLogin // ignore: cast_nullable_to_non_nullable -as String?,language: freezed == language ? _self.language : language // ignore: cast_nullable_to_non_nullable -as String?,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable +firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable -as String?,hasApiKey: freezed == hasApiKey ? _self.hasApiKey : hasApiKey // ignore: cast_nullable_to_non_nullable as String?,phone: freezed == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable as String?, )); diff --git a/modules/legacy/modules/account/lib/src/features/personal_data/personal_data_builder.dart b/modules/legacy/modules/account/lib/src/features/personal_data/personal_data_builder.dart index b06d2cdc..29dfdece 100644 --- a/modules/legacy/modules/account/lib/src/features/personal_data/personal_data_builder.dart +++ b/modules/legacy/modules/account/lib/src/features/personal_data/personal_data_builder.dart @@ -1,19 +1,14 @@ -// import 'package:account/src/features/account_settings/presentation/account_settings_screen.dart'; import 'package:account/src/features/personal_data/presentation/personal_data_screen.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:get_it/get_it.dart'; -import 'package:navigation/navigation.dart'; class PersonalDataBuilder { const PersonalDataBuilder(); Page buildPage(BuildContext context, GoRouterState state) { - final NavigationContract navigationContract = GetIt.I(); - return MaterialPage( key: state.pageKey, - child: PersonalDataScreen(navigationContract: navigationContract), + child: const PersonalDataScreen(), ); } } diff --git a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart index 08854e1c..c426f0a5 100644 --- a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart @@ -4,286 +4,196 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:legacy_shared/legacy_shared.dart'; -import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; class PersonalDataScreen extends ConsumerWidget { - final NavigationContract navigationContract; - - const PersonalDataScreen({super.key, required this.navigationContract}); + const PersonalDataScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.watch(themePortProvider); + final isLoading = ref.watch( + personalDataViewModelProvider.select((s) => s.isLoading), + ); + + ref.listen(personalDataViewModelProvider.select((s) => s.errorMessage), ( + _, + errorMessage, + ) { + if (errorMessage.isNotEmpty) { + showTopSnackbar( + context, + message: errorMessage, + type: MessageType.error, + ); + } + }); + + ref.listen(personalDataViewModelProvider.select((s) => s.isComplete), ( + _, + isComplete, + ) { + if (isComplete) Navigator.pop(context); + }); + + if (isLoading) { + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), + body: const Center(child: CircularProgressIndicator()), + ); + } return LegacyPageLayout( theme: theme, title: context.translate(I18n.personalData), - body: Container( + body: Padding( padding: SizeUtils.getByScreen( small: EdgeInsets.symmetric(horizontal: 48, vertical: 10), - big: EdgeInsets.symmetric(horizontal: 47, vertical: 8) + big: EdgeInsets.symmetric(horizontal: 47, vertical: 8), + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const _ProfilePicture(), + SizedBox(height: SizeUtils.getByScreen(small: 18, big: 16)), + const _EmailLabel(), + SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)), + const _FirstNameField(), + SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)), + const _LastNameField(), + SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)), + const _PhoneField(), + ], + ), + ), + ), + footer: Padding( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 48), + big: EdgeInsets.symmetric(horizontal: 47), + ), + child: Column( + children: [ + Text(context.translate(I18n.personalDataMessage)), + const SizedBox(height: 14), + const _SaveButton(), + ], ), - child: SingleChildScrollView(child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const _ProfilePictureSection(), - SizedBox(height: SizeUtils.getByScreen(small: 18, big: 16)), - const _EmailLabelSection(), - SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)), - const _GenderSection(), - SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)), - const _NameSection(), - SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)), - const _PhoneSection(), - SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)), - const _EmailSection(), - ], - )) ), - footer: Column( - children: [ - Text(context.translate(I18n.personalDataMessage)), - SizedBox(height: 14), - const _SaveSection(), - ], - ) ); } } -class _ProfilePictureSection extends ConsumerWidget { - - const _ProfilePictureSection(); +class _ProfilePicture extends StatelessWidget { + const _ProfilePicture(); @override - Widget build(BuildContext context, WidgetRef ref) { - return Stack( - children: [ - Center(child: Container( - decoration: BoxDecoration(shape: BoxShape.circle), - child: SvgPicture.asset('assets/images/ui/profile.svg')), - ), - Center(child: SizedBox( - width: 160, - height: 160, - child: Align(alignment: Alignment.bottomRight, - child: IconButton( - onPressed: (){}, - icon: Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Color(0xFFCAC9C9) - ), - padding: EdgeInsets.all(8), - child: Icon( - Icons.edit_outlined, - color: Colors.white, - size: SizeUtils.getByScreen(small: 32, big: 30), - ), - ), - ) - ) - )) - ], + Widget build(BuildContext context) { + return Center( + child: Container( + decoration: const BoxDecoration(shape: BoxShape.circle), + child: SvgPicture.asset('assets/shared/images/profile.svg'), + ), ); } - } -class _EmailLabelSection extends ConsumerWidget { - - const _EmailLabelSection(); +class _EmailLabel extends ConsumerWidget { + const _EmailLabel(); @override Widget build(BuildContext context, WidgetRef ref) { final email = ref.watch( - personalDataViewModelProvider.select((s)=>s.user?.email ?? '') + personalDataViewModelProvider.select((s) => s.user?.email ?? ''), ); return Column( children: [ - Text(context.translate(I18n.emailLabel), - style: TextStyle(fontSize: SizeUtils.getByScreen(small: 14, big: 13)) + Text( + context.translate(I18n.emailLabel), + style: TextStyle(fontSize: SizeUtils.getByScreen(small: 14, big: 13)), ), - Text(email, - style: TextStyle(fontSize: SizeUtils.getByScreen(small: 18, big: 17)) + Text( + email, + style: TextStyle(fontSize: SizeUtils.getByScreen(small: 18, big: 17)), ), ], ); } - -} - -class _GenderSection extends ConsumerWidget { - - const _GenderSection(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - final vm = ref.read(personalDataViewModelProvider.notifier); - final gender = ref.watch( - personalDataViewModelProvider.select((s)=>s.gender) - ); - - Map genderOptions = { - 'M': context.translate(I18n.male), - 'F': context.translate(I18n.female), - 'O': context.translate(I18n.ratherNotSay), - }; - - final setGender = (value){vm.setGender(value.toString());}; - - return Column( - children: [ - Align( - alignment: Alignment.bottomLeft, - child: Text(context.translate(I18n.genderLabel),), - ), - Container( - decoration: BoxDecoration( - border: Border.fromBorderSide(BorderSide( - color: theme.getColorFor(ThemeCode.legacyPrimary), - width: 3 - )), - borderRadius: BorderRadius.all(Radius.circular(32)), - ), - padding: EdgeInsets.symmetric(horizontal: 10), - child: RadioGroup( - onChanged: setGender, - groupValue: gender, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: List.generate(genderOptions.length, (int index)=> - Row( - children: [ - Radio( - value: genderOptions.keys.elementAt(index), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - TextButton( - onPressed: (){setGender(genderOptions.keys.elementAt(index));}, - style: TextButton.styleFrom( - padding: EdgeInsets.zero, - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - child: Text(genderOptions.values.elementAt(index), - style: TextStyle(fontSize: 10), - ), - ), - ], - ) - ) - ), - ), - ) - ], - ); - } } -class _NameSection extends ConsumerWidget { - - const _NameSection(); +class _FirstNameField extends ConsumerWidget { + const _FirstNameField(); @override Widget build(BuildContext context, WidgetRef ref) { final vm = ref.read(personalDataViewModelProvider.notifier); - final name = ref.watch( - personalDataViewModelProvider.select((s)=>s.user?.firstName ?? '') + final hint = ref.watch( + personalDataViewModelProvider.select((s) => s.user?.firstName ?? ''), ); return CustomTextField( - controller: vm.nameController, - hint: name, + controller: vm.firstNameController, + hint: hint, label: context.translate(I18n.firstNameLabel), ); } - } -class _PhoneSection extends ConsumerWidget { - - const _PhoneSection(); +class _LastNameField extends ConsumerWidget { + const _LastNameField(); @override Widget build(BuildContext context, WidgetRef ref) { final vm = ref.read(personalDataViewModelProvider.notifier); - final phone = ref.watch( - personalDataViewModelProvider.select((s)=>s.user?.phone ?? '') + final hint = ref.watch( + personalDataViewModelProvider.select((s) => s.user?.lastName ?? ''), + ); + + return CustomTextField( + controller: vm.lastNameController, + hint: hint, + label: context.translate(I18n.lastNameLabel), + ); + } +} + +class _PhoneField extends ConsumerWidget { + const _PhoneField(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final vm = ref.read(personalDataViewModelProvider.notifier); + final hint = ref.watch( + personalDataViewModelProvider.select((s) => s.user?.phone ?? ''), ); return CustomTextField( controller: vm.phoneController, - hint: phone, + hint: hint, label: context.translate(I18n.phoneLabel), keyboardType: TextInputType.phone, ); } - } -class _EmailSection extends ConsumerWidget { - - const _EmailSection(); +class _SaveButton extends ConsumerWidget { + const _SaveButton(); @override Widget build(BuildContext context, WidgetRef ref) { - final vm = ref.read(personalDataViewModelProvider.notifier); - final email = ref.watch( - personalDataViewModelProvider.select((s)=>s.user?.email ?? '') - ); - - return CustomTextField( - controller: vm.emailController, - hint: email, - label: context.translate(I18n.emailLabel), - keyboardType: TextInputType.emailAddress, - ); - } - -} - -class _SaveSection extends ConsumerWidget { - - const _SaveSection(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - + final theme = ref.watch(themePortProvider); final vm = ref.read(personalDataViewModelProvider.notifier); return Padding( - padding: EdgeInsets.symmetric(horizontal: 24, vertical: 10), + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10), child: PrimaryButton( - onPressed: () async { - await vm.updateUser(); - - final errorMessage = ref.read( - personalDataViewModelProvider.select((s)=>s.errorMessage) - ); - if (errorMessage.isNotEmpty) { - showTopSnackbar(context, message: errorMessage, type: MessageType.error); - return; - } - - final isComplete = ref.read( - personalDataViewModelProvider.select((s)=>s.isComplete) - ); - if (isComplete) { - Navigator.pop(context); - } - }, + onPressed: vm.updateUser, text: context.translate(I18n.submit), - color: theme.getColorFor(ThemeCode.legacyPrimary) + color: theme.getColorFor(ThemeCode.legacyPrimary), ), ); } - -} \ No newline at end of file +} diff --git a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_model.dart b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_model.dart index c24783dd..e5587898 100644 --- a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_model.dart +++ b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_model.dart @@ -8,165 +8,91 @@ import '../../../../core/domain/repositories/users_repository.dart'; import '../../../../core/providers/users_repository_provider.dart'; final personalDataViewModelProvider = -NotifierProvider.autoDispose( - PersonalDataViewModel.new, -); + NotifierProvider.autoDispose( + PersonalDataViewModel.new, + ); class PersonalDataViewModel extends Notifier { late final UsersRepository _usersRepository; - late final TextEditingController nameController; - late final TextEditingController emailController; + late final TextEditingController firstNameController; + late final TextEditingController lastNameController; late final TextEditingController phoneController; - late final TextEditingController passwordController; @override PersonalDataViewState build() { _usersRepository = ref.read(usersRepositoryProvider); - nameController = TextEditingController(); - nameController.addListener(_onNameChanged); - - emailController = TextEditingController(); - emailController.addListener(_onEmailChanged); - + firstNameController = TextEditingController(); + lastNameController = TextEditingController(); phoneController = TextEditingController(); - phoneController.addListener(_onPhoneChanged); - passwordController = TextEditingController(); - passwordController.addListener(_onPasswordChanged); + Future.microtask(_init); - _init(); - - ref.onDispose(disposeControllers); + ref.onDispose(_disposeControllers); return const PersonalDataViewState(); } Future _init() async { final user = await ref.read(userInfoProvider.future); - setUser(user); + state = state.copyWith(user: user, isLoading: false); } - void setUser(UserEntity user) { - state = state.copyWith(user: user); - } - - void setGender(String value) { - if (value == state.gender) return; - - state = state.copyWith( - gender: value, - ); - } - - void _onNameChanged() { - final value = nameController.text; - - if (value == state.name) return; - - state = state.copyWith( - name: value, - ); - } - - void _onEmailChanged() { - final value = emailController.text; - - if (value == state.email) return; - - state = state.copyWith( - email: value, - ); - } - - void _onPhoneChanged() { - final value = phoneController.text; - - if (value == state.phoneNumber) return; - - state = state.copyWith( - phoneNumber: value, - ); - } - - void _onPasswordChanged() { - final value = passwordController.text; - - if (value == state.password) return; - - state = state.copyWith( - password: value, - ); - } - - bool _validateForm() { - if (state.name.trim().isEmpty && - state.email.trim().isEmpty && - state.phoneNumber.trim().isEmpty && - state.password.trim().isEmpty) { - state = state.copyWith(errorMessage: 'errorMessageAllFieldsAreEmpty'); - return false; - } - return true; - } + bool get _hasChanges => + firstNameController.text.trim().isNotEmpty || + lastNameController.text.trim().isNotEmpty || + phoneController.text.trim().isNotEmpty; UpdateUserRequestEntity _toRequest() { - return UpdateUserRequestEntity( - id: state.user!.id, - //name: state.name.trim(), - email: state.email.trim(), - phone: /*state.dialCode.trim() + */state.phoneNumber.trim(), + firstName: firstNameController.text.trim().isNotEmpty + ? firstNameController.text.trim() + : null, + lastName: lastNameController.text.trim().isNotEmpty + ? lastNameController.text.trim() + : null, + phone: phoneController.text.trim().isNotEmpty + ? phoneController.text.trim() + : null, ); } Future updateUser() async { - try { - state = state.copyWith( - isLoading: true, - isComplete: false, - ); + if (state.isLoading || !_hasChanges) return; - if (!_validateForm()) return; + try { + state = state.copyWith(isLoading: true, isComplete: false, errorMessage: ''); final request = _toRequest(); - _usersRepository.updateUser(userId: state.user!.id, request: request); - ref.invalidate(userInfoProvider); - - state = state.copyWith( - isLoading: false, - isComplete: true, + await _usersRepository.updateUser( + userId: state.user!.id, + request: request, ); - return; + if (!ref.mounted) return; + + final updatedUser = state.user!.copyWith( + firstName: request.firstName ?? state.user!.firstName, + lastName: request.lastName ?? state.user!.lastName, + phone: request.phone ?? state.user!.phone, + ); + ref.read(userInfoProvider.notifier).setUser(updatedUser); + + state = state.copyWith(isLoading: false, isComplete: true); } catch (e) { if (!ref.mounted) return; - _finishWithError(message: e.toString()); + state = state.copyWith( + isLoading: false, + isComplete: false, + errorMessage: e.toString(), + ); } - } - void _finishWithError({required String message}) { - state = state.copyWith( - isLoading: false, - isComplete: false, - errorMessage: message, - ); - } - - void disposeControllers() { - nameController.removeListener(_onNameChanged); - nameController.dispose(); - - emailController.removeListener(_onEmailChanged); - emailController.dispose(); - - phoneController.removeListener(_onPhoneChanged); + void _disposeControllers() { + firstNameController.dispose(); + lastNameController.dispose(); phoneController.dispose(); - - passwordController.removeListener(_onPasswordChanged); - passwordController.dispose(); - } -} \ No newline at end of file +} diff --git a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_state.dart b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_state.dart index acac4022..1b05c3a6 100644 --- a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_state.dart +++ b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_state.dart @@ -9,12 +9,6 @@ abstract class PersonalDataViewState with _$PersonalDataViewState { @Default(true) bool isLoading, @Default(false) bool isComplete, UserEntity? user, - @Default('O') String gender, - @Default('') String name, - @Default('') String phoneNumber, - @Default('') String email, - @Default('') String password, - @Default(false) bool showPassword, - @Default('') String errorMessage + @Default('') String errorMessage, }) = _PersonalDataViewState; } diff --git a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_state.freezed.dart b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_state.freezed.dart index eb69d4b1..e932c958 100644 --- a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_state.freezed.dart +++ b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/state/personal_data_view_state.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$PersonalDataViewState { - bool get isLoading; bool get isComplete; UserEntity? get user; String get gender; String get name; String get phoneNumber; String get email; String get password; bool get showPassword; String get errorMessage; + bool get isLoading; bool get isComplete; UserEntity? get user; String get errorMessage; /// Create a copy of PersonalDataViewState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $PersonalDataViewStateCopyWith get copyWith => _$Personal @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is PersonalDataViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.user, user) || other.user == user)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.name, name) || other.name == name)&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.email, email) || other.email == email)&&(identical(other.password, password) || other.password == password)&&(identical(other.showPassword, showPassword) || other.showPassword == showPassword)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is PersonalDataViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.user, user) || other.user == user)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,isLoading,isComplete,user,gender,name,phoneNumber,email,password,showPassword,errorMessage); +int get hashCode => Object.hash(runtimeType,isLoading,isComplete,user,errorMessage); @override String toString() { - return 'PersonalDataViewState(isLoading: $isLoading, isComplete: $isComplete, user: $user, gender: $gender, name: $name, phoneNumber: $phoneNumber, email: $email, password: $password, showPassword: $showPassword, errorMessage: $errorMessage)'; + return 'PersonalDataViewState(isLoading: $isLoading, isComplete: $isComplete, user: $user, errorMessage: $errorMessage)'; } @@ -45,7 +45,7 @@ abstract mixin class $PersonalDataViewStateCopyWith<$Res> { factory $PersonalDataViewStateCopyWith(PersonalDataViewState value, $Res Function(PersonalDataViewState) _then) = _$PersonalDataViewStateCopyWithImpl; @useResult $Res call({ - bool isLoading, bool isComplete, UserEntity? user, String gender, String name, String phoneNumber, String email, String password, bool showPassword, String errorMessage + bool isLoading, bool isComplete, UserEntity? user, String errorMessage }); @@ -62,18 +62,12 @@ class _$PersonalDataViewStateCopyWithImpl<$Res> /// Create a copy of PersonalDataViewState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? isComplete = null,Object? user = freezed,Object? gender = null,Object? name = null,Object? phoneNumber = null,Object? email = null,Object? password = null,Object? showPassword = null,Object? errorMessage = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? isComplete = null,Object? user = freezed,Object? errorMessage = null,}) { return _then(_self.copyWith( isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable as bool,isComplete: null == isComplete ? _self.isComplete : isComplete // ignore: cast_nullable_to_non_nullable as bool,user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable -as UserEntity?,gender: null == gender ? _self.gender : gender // ignore: cast_nullable_to_non_nullable -as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable -as String,phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable -as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable -as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable -as String,showPassword: null == showPassword ? _self.showPassword : showPassword // ignore: cast_nullable_to_non_nullable -as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as UserEntity?,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String, )); } @@ -171,10 +165,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( bool isLoading, bool isComplete, UserEntity? user, String gender, String name, String phoneNumber, String email, String password, bool showPassword, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( bool isLoading, bool isComplete, UserEntity? user, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _PersonalDataViewState() when $default != null: -return $default(_that.isLoading,_that.isComplete,_that.user,_that.gender,_that.name,_that.phoneNumber,_that.email,_that.password,_that.showPassword,_that.errorMessage);case _: +return $default(_that.isLoading,_that.isComplete,_that.user,_that.errorMessage);case _: return orElse(); } @@ -192,10 +186,10 @@ return $default(_that.isLoading,_that.isComplete,_that.user,_that.gender,_that.n /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( bool isLoading, bool isComplete, UserEntity? user, String gender, String name, String phoneNumber, String email, String password, bool showPassword, String errorMessage) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( bool isLoading, bool isComplete, UserEntity? user, String errorMessage) $default,) {final _that = this; switch (_that) { case _PersonalDataViewState(): -return $default(_that.isLoading,_that.isComplete,_that.user,_that.gender,_that.name,_that.phoneNumber,_that.email,_that.password,_that.showPassword,_that.errorMessage);case _: +return $default(_that.isLoading,_that.isComplete,_that.user,_that.errorMessage);case _: throw StateError('Unexpected subclass'); } @@ -212,10 +206,10 @@ return $default(_that.isLoading,_that.isComplete,_that.user,_that.gender,_that.n /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool isLoading, bool isComplete, UserEntity? user, String gender, String name, String phoneNumber, String email, String password, bool showPassword, String errorMessage)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool isLoading, bool isComplete, UserEntity? user, String errorMessage)? $default,) {final _that = this; switch (_that) { case _PersonalDataViewState() when $default != null: -return $default(_that.isLoading,_that.isComplete,_that.user,_that.gender,_that.name,_that.phoneNumber,_that.email,_that.password,_that.showPassword,_that.errorMessage);case _: +return $default(_that.isLoading,_that.isComplete,_that.user,_that.errorMessage);case _: return null; } @@ -227,18 +221,12 @@ return $default(_that.isLoading,_that.isComplete,_that.user,_that.gender,_that.n class _PersonalDataViewState implements PersonalDataViewState { - const _PersonalDataViewState({this.isLoading = true, this.isComplete = false, this.user, this.gender = 'O', this.name = '', this.phoneNumber = '', this.email = '', this.password = '', this.showPassword = false, this.errorMessage = ''}); + const _PersonalDataViewState({this.isLoading = true, this.isComplete = false, this.user, this.errorMessage = ''}); @override@JsonKey() final bool isLoading; @override@JsonKey() final bool isComplete; @override final UserEntity? user; -@override@JsonKey() final String gender; -@override@JsonKey() final String name; -@override@JsonKey() final String phoneNumber; -@override@JsonKey() final String email; -@override@JsonKey() final String password; -@override@JsonKey() final bool showPassword; @override@JsonKey() final String errorMessage; /// Create a copy of PersonalDataViewState @@ -251,16 +239,16 @@ _$PersonalDataViewStateCopyWith<_PersonalDataViewState> get copyWith => __$Perso @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _PersonalDataViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.user, user) || other.user == user)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.name, name) || other.name == name)&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.email, email) || other.email == email)&&(identical(other.password, password) || other.password == password)&&(identical(other.showPassword, showPassword) || other.showPassword == showPassword)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _PersonalDataViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.user, user) || other.user == user)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,isLoading,isComplete,user,gender,name,phoneNumber,email,password,showPassword,errorMessage); +int get hashCode => Object.hash(runtimeType,isLoading,isComplete,user,errorMessage); @override String toString() { - return 'PersonalDataViewState(isLoading: $isLoading, isComplete: $isComplete, user: $user, gender: $gender, name: $name, phoneNumber: $phoneNumber, email: $email, password: $password, showPassword: $showPassword, errorMessage: $errorMessage)'; + return 'PersonalDataViewState(isLoading: $isLoading, isComplete: $isComplete, user: $user, errorMessage: $errorMessage)'; } @@ -271,7 +259,7 @@ abstract mixin class _$PersonalDataViewStateCopyWith<$Res> implements $PersonalD factory _$PersonalDataViewStateCopyWith(_PersonalDataViewState value, $Res Function(_PersonalDataViewState) _then) = __$PersonalDataViewStateCopyWithImpl; @override @useResult $Res call({ - bool isLoading, bool isComplete, UserEntity? user, String gender, String name, String phoneNumber, String email, String password, bool showPassword, String errorMessage + bool isLoading, bool isComplete, UserEntity? user, String errorMessage }); @@ -288,18 +276,12 @@ class __$PersonalDataViewStateCopyWithImpl<$Res> /// Create a copy of PersonalDataViewState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? isComplete = null,Object? user = freezed,Object? gender = null,Object? name = null,Object? phoneNumber = null,Object? email = null,Object? password = null,Object? showPassword = null,Object? errorMessage = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? isComplete = null,Object? user = freezed,Object? errorMessage = null,}) { return _then(_PersonalDataViewState( isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable as bool,isComplete: null == isComplete ? _self.isComplete : isComplete // ignore: cast_nullable_to_non_nullable as bool,user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable -as UserEntity?,gender: null == gender ? _self.gender : gender // ignore: cast_nullable_to_non_nullable -as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable -as String,phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable -as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable -as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable -as String,showPassword: null == showPassword ? _self.showPassword : showPassword // ignore: cast_nullable_to_non_nullable -as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as UserEntity?,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String, )); } diff --git a/modules/legacy/modules/account/pubspec_overrides.yaml b/modules/legacy/modules/account/pubspec_overrides.yaml index 498ed0b7..5c2da064 100644 --- a/modules/legacy/modules/account/pubspec_overrides.yaml +++ b/modules/legacy/modules/account/pubspec_overrides.yaml @@ -14,7 +14,7 @@ dependency_overrides: home: path: ../../../home legacy_auth: - path: ..\\legacy_auth + path: ../legacy_auth legacy_shared: path: ../../packages/legacy_shared navigation: diff --git a/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/control_panel_screen.dart b/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/control_panel_screen.dart index 58854019..2c102ca7 100644 --- a/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/control_panel_screen.dart +++ b/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/control_panel_screen.dart @@ -62,7 +62,7 @@ class ControlPanelScreen extends ConsumerWidget { SizedBox( height: SizeUtils.getByScreen(small: 16, big: 22), ), - _MapSection(), + _MapSection(navigationContract: navigationContract), SizedBox( height: SizeUtils.getByScreen(small: 14, big: 13), ), @@ -104,12 +104,13 @@ class _Header extends ConsumerWidget { child: CustomDropdown( items: state.devices .map( - (DeviceEntity device) => Text( - device.carrierName!.length > 10 - ? '${device.carrierName!.substring(0, 10)}...' - : device.carrierName!, - overflow: TextOverflow.ellipsis, - ), + (DeviceEntity device) { + final name = device.carrierName ?? ''; + return Text( + name.length > 10 ? '${name.substring(0, 10)}...' : name, + overflow: TextOverflow.ellipsis, + ); + }, ) .toList(), values: state.devices, @@ -162,7 +163,7 @@ class _MenuSection extends ConsumerWidget { SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), _SectionButton( onPressed: () { - navigationContract.pushTo(AppRoutes.deviceManagement); + navigationContract.goTo(AppRoutes.deviceManagement); }, icon: SFIcons.functions, text: I18n.functions, @@ -201,7 +202,7 @@ class _SectionButton extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); + final theme = ref.watch(themePortProvider); return SectionButton( onPressed: onPressed, @@ -224,7 +225,9 @@ class _SectionButton extends ConsumerWidget { } class _MapSection extends ConsumerWidget { - const _MapSection(); + final NavigationContract navigationContract; + + const _MapSection({required this.navigationContract}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -232,38 +235,44 @@ class _MapSection extends ConsumerWidget { final state = ref.watch(controlPanelViewModelProvider); final vm = ref.read(controlPanelViewModelProvider.notifier); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - context.translate(I18n.watchesOnMap), - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 20, big: 19), - fontWeight: FontWeight.bold, - color: theme.getColorFor(ThemeCode.legacyPrimary), + return GestureDetector( + onTap: () => navigationContract.goTo(AppRoutes.legacyLocation), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + context.translate(I18n.watchesOnMap), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 19), + fontWeight: FontWeight.bold, + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), ), - ), - IconButton( - onPressed: vm.refreshPositions, - icon: Icon( - Icons.refresh, - color: theme.getColorFor(ThemeCode.legacyPrimary), + IconButton( + onPressed: vm.refreshPositions, + icon: Icon( + Icons.refresh, + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), ), - ), - ], - ), - SizedBox(height: SizeUtils.getByScreen(small: 4, big: 8)), - SizedBox( - height: SizeUtils.getByScreen(small: 200, big: 300), - child: DeviceMap( - selectedPosition: state.selectedPosition, - selectedDevice: state.selectedDevice, + ], ), - ), - ], + SizedBox(height: SizeUtils.getByScreen(small: 4, big: 8)), + AbsorbPointer( + child: SizedBox( + height: SizeUtils.getByScreen(small: 200, big: 300), + child: DeviceMap( + selectedPosition: state.selectedPosition, + selectedDevice: state.selectedDevice, + markerSize: 40, + ), + ), + ), + ], + ), ); } } diff --git a/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_model.dart b/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_model.dart index df5ff5d8..c735b736 100644 --- a/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_model.dart +++ b/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_model.dart @@ -27,10 +27,6 @@ class ControlPanelViewModel extends Notifier { Future _init() async { try { - final user = await ref.read(userInfoProvider.future); - if (!ref.mounted) return; - state = state.copyWith(loggedUser: user); - final devices = await _devicesRepository.getDevices(); if (!ref.mounted) return; @@ -39,15 +35,21 @@ class ControlPanelViewModel extends Notifier { return; } + final previouslySelected = ref.read(selectedDeviceProvider); + final selected = previouslySelected != null && + devices.any((d) => d.identificator == previouslySelected.identificator) + ? previouslySelected + : devices.first; + state = state.copyWith( devices: devices, - selectedDevice: devices.first, + selectedDevice: selected, ); - _selectedDeviceNotifier.setSelectedDevice(devices.first); + _selectedDeviceNotifier.setSelectedDevice(selected); final positionLists = await Future.wait( devices.map( - (d) => _controlPanelRepository.getLatestPositions(deviceId: d!.identificator), + (d) => _controlPanelRepository.getLatestPositions(deviceId: d.identificator), ), ); if (!ref.mounted) return; @@ -93,7 +95,7 @@ class ControlPanelViewModel extends Notifier { try { final positionLists = await Future.wait( state.devices.map( - (d) => _controlPanelRepository.getLatestPositions(deviceId: d!.identificator), + (d) => _controlPanelRepository.getLatestPositions(deviceId: d.identificator), ), ); if (!ref.mounted) return; diff --git a/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_state.dart b/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_state.dart index 1cb1a827..c9d047ee 100644 --- a/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_state.dart +++ b/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_state.dart @@ -7,7 +7,6 @@ part 'control_panel_view_state.freezed.dart'; @freezed abstract class ControlPanelViewState with _$ControlPanelViewState { const factory ControlPanelViewState({ - UserEntity? loggedUser, @Default([]) List devices, DeviceEntity? selectedDevice, @Default([]) List positions, diff --git a/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_state.freezed.dart b/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_state.freezed.dart index 29c383d8..2ce58f3f 100644 --- a/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_state.freezed.dart +++ b/modules/legacy/modules/control_panel/lib/src/features/control_panel/presentation/state/control_panel_view_state.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$ControlPanelViewState { - UserEntity? get loggedUser; List get devices; DeviceEntity? get selectedDevice; List get positions; PositionEntity? get selectedPosition; bool get isLoading; String get errorMessage; + List get devices; DeviceEntity? get selectedDevice; List get positions; PositionEntity? get selectedPosition; bool get isLoading; String get errorMessage; /// Create a copy of ControlPanelViewState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $ControlPanelViewStateCopyWith get copyWith => _$ControlP @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is ControlPanelViewState&&(identical(other.loggedUser, loggedUser) || other.loggedUser == loggedUser)&&const DeepCollectionEquality().equals(other.devices, devices)&&(identical(other.selectedDevice, selectedDevice) || other.selectedDevice == selectedDevice)&&const DeepCollectionEquality().equals(other.positions, positions)&&(identical(other.selectedPosition, selectedPosition) || other.selectedPosition == selectedPosition)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is ControlPanelViewState&&const DeepCollectionEquality().equals(other.devices, devices)&&(identical(other.selectedDevice, selectedDevice) || other.selectedDevice == selectedDevice)&&const DeepCollectionEquality().equals(other.positions, positions)&&(identical(other.selectedPosition, selectedPosition) || other.selectedPosition == selectedPosition)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,loggedUser,const DeepCollectionEquality().hash(devices),selectedDevice,const DeepCollectionEquality().hash(positions),selectedPosition,isLoading,errorMessage); +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(devices),selectedDevice,const DeepCollectionEquality().hash(positions),selectedPosition,isLoading,errorMessage); @override String toString() { - return 'ControlPanelViewState(loggedUser: $loggedUser, devices: $devices, selectedDevice: $selectedDevice, positions: $positions, selectedPosition: $selectedPosition, isLoading: $isLoading, errorMessage: $errorMessage)'; + return 'ControlPanelViewState(devices: $devices, selectedDevice: $selectedDevice, positions: $positions, selectedPosition: $selectedPosition, isLoading: $isLoading, errorMessage: $errorMessage)'; } @@ -45,11 +45,11 @@ abstract mixin class $ControlPanelViewStateCopyWith<$Res> { factory $ControlPanelViewStateCopyWith(ControlPanelViewState value, $Res Function(ControlPanelViewState) _then) = _$ControlPanelViewStateCopyWithImpl; @useResult $Res call({ - UserEntity? loggedUser, List devices, DeviceEntity? selectedDevice, List positions, PositionEntity? selectedPosition, bool isLoading, String errorMessage + List devices, DeviceEntity? selectedDevice, List positions, PositionEntity? selectedPosition, bool isLoading, String errorMessage }); -$UserEntityCopyWith<$Res>? get loggedUser;$DeviceEntityCopyWith<$Res>? get selectedDevice;$PositionEntityCopyWith<$Res>? get selectedPosition; +$DeviceEntityCopyWith<$Res>? get selectedDevice;$PositionEntityCopyWith<$Res>? get selectedPosition; } /// @nodoc @@ -62,10 +62,9 @@ class _$ControlPanelViewStateCopyWithImpl<$Res> /// Create a copy of ControlPanelViewState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? loggedUser = freezed,Object? devices = null,Object? selectedDevice = freezed,Object? positions = null,Object? selectedPosition = freezed,Object? isLoading = null,Object? errorMessage = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? devices = null,Object? selectedDevice = freezed,Object? positions = null,Object? selectedPosition = freezed,Object? isLoading = null,Object? errorMessage = null,}) { return _then(_self.copyWith( -loggedUser: freezed == loggedUser ? _self.loggedUser : loggedUser // ignore: cast_nullable_to_non_nullable -as UserEntity?,devices: null == devices ? _self.devices : devices // ignore: cast_nullable_to_non_nullable +devices: null == devices ? _self.devices : devices // ignore: cast_nullable_to_non_nullable as List,selectedDevice: freezed == selectedDevice ? _self.selectedDevice : selectedDevice // ignore: cast_nullable_to_non_nullable as DeviceEntity?,positions: null == positions ? _self.positions : positions // ignore: cast_nullable_to_non_nullable as List,selectedPosition: freezed == selectedPosition ? _self.selectedPosition : selectedPosition // ignore: cast_nullable_to_non_nullable @@ -78,18 +77,6 @@ as String, /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') -$UserEntityCopyWith<$Res>? get loggedUser { - if (_self.loggedUser == null) { - return null; - } - - return $UserEntityCopyWith<$Res>(_self.loggedUser!, (value) { - return _then(_self.copyWith(loggedUser: value)); - }); -}/// Create a copy of ControlPanelViewState -/// with the given fields replaced by the non-null parameter values. -@override -@pragma('vm:prefer-inline') $DeviceEntityCopyWith<$Res>? get selectedDevice { if (_self.selectedDevice == null) { return null; @@ -192,10 +179,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( UserEntity? loggedUser, List devices, DeviceEntity? selectedDevice, List positions, PositionEntity? selectedPosition, bool isLoading, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( List devices, DeviceEntity? selectedDevice, List positions, PositionEntity? selectedPosition, bool isLoading, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _ControlPanelViewState() when $default != null: -return $default(_that.loggedUser,_that.devices,_that.selectedDevice,_that.positions,_that.selectedPosition,_that.isLoading,_that.errorMessage);case _: +return $default(_that.devices,_that.selectedDevice,_that.positions,_that.selectedPosition,_that.isLoading,_that.errorMessage);case _: return orElse(); } @@ -213,10 +200,10 @@ return $default(_that.loggedUser,_that.devices,_that.selectedDevice,_that.positi /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( UserEntity? loggedUser, List devices, DeviceEntity? selectedDevice, List positions, PositionEntity? selectedPosition, bool isLoading, String errorMessage) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( List devices, DeviceEntity? selectedDevice, List positions, PositionEntity? selectedPosition, bool isLoading, String errorMessage) $default,) {final _that = this; switch (_that) { case _ControlPanelViewState(): -return $default(_that.loggedUser,_that.devices,_that.selectedDevice,_that.positions,_that.selectedPosition,_that.isLoading,_that.errorMessage);case _: +return $default(_that.devices,_that.selectedDevice,_that.positions,_that.selectedPosition,_that.isLoading,_that.errorMessage);case _: throw StateError('Unexpected subclass'); } @@ -233,10 +220,10 @@ return $default(_that.loggedUser,_that.devices,_that.selectedDevice,_that.positi /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( UserEntity? loggedUser, List devices, DeviceEntity? selectedDevice, List positions, PositionEntity? selectedPosition, bool isLoading, String errorMessage)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List devices, DeviceEntity? selectedDevice, List positions, PositionEntity? selectedPosition, bool isLoading, String errorMessage)? $default,) {final _that = this; switch (_that) { case _ControlPanelViewState() when $default != null: -return $default(_that.loggedUser,_that.devices,_that.selectedDevice,_that.positions,_that.selectedPosition,_that.isLoading,_that.errorMessage);case _: +return $default(_that.devices,_that.selectedDevice,_that.positions,_that.selectedPosition,_that.isLoading,_that.errorMessage);case _: return null; } @@ -248,10 +235,9 @@ return $default(_that.loggedUser,_that.devices,_that.selectedDevice,_that.positi class _ControlPanelViewState implements ControlPanelViewState { - const _ControlPanelViewState({this.loggedUser, final List devices = const [], this.selectedDevice, final List positions = const [], this.selectedPosition, this.isLoading = true, this.errorMessage = ''}): _devices = devices,_positions = positions; + const _ControlPanelViewState({final List devices = const [], this.selectedDevice, final List positions = const [], this.selectedPosition, this.isLoading = true, this.errorMessage = ''}): _devices = devices,_positions = positions; -@override final UserEntity? loggedUser; final List _devices; @override@JsonKey() List get devices { if (_devices is EqualUnmodifiableListView) return _devices; @@ -281,16 +267,16 @@ _$ControlPanelViewStateCopyWith<_ControlPanelViewState> get copyWith => __$Contr @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _ControlPanelViewState&&(identical(other.loggedUser, loggedUser) || other.loggedUser == loggedUser)&&const DeepCollectionEquality().equals(other._devices, _devices)&&(identical(other.selectedDevice, selectedDevice) || other.selectedDevice == selectedDevice)&&const DeepCollectionEquality().equals(other._positions, _positions)&&(identical(other.selectedPosition, selectedPosition) || other.selectedPosition == selectedPosition)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ControlPanelViewState&&const DeepCollectionEquality().equals(other._devices, _devices)&&(identical(other.selectedDevice, selectedDevice) || other.selectedDevice == selectedDevice)&&const DeepCollectionEquality().equals(other._positions, _positions)&&(identical(other.selectedPosition, selectedPosition) || other.selectedPosition == selectedPosition)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,loggedUser,const DeepCollectionEquality().hash(_devices),selectedDevice,const DeepCollectionEquality().hash(_positions),selectedPosition,isLoading,errorMessage); +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_devices),selectedDevice,const DeepCollectionEquality().hash(_positions),selectedPosition,isLoading,errorMessage); @override String toString() { - return 'ControlPanelViewState(loggedUser: $loggedUser, devices: $devices, selectedDevice: $selectedDevice, positions: $positions, selectedPosition: $selectedPosition, isLoading: $isLoading, errorMessage: $errorMessage)'; + return 'ControlPanelViewState(devices: $devices, selectedDevice: $selectedDevice, positions: $positions, selectedPosition: $selectedPosition, isLoading: $isLoading, errorMessage: $errorMessage)'; } @@ -301,11 +287,11 @@ abstract mixin class _$ControlPanelViewStateCopyWith<$Res> implements $ControlPa factory _$ControlPanelViewStateCopyWith(_ControlPanelViewState value, $Res Function(_ControlPanelViewState) _then) = __$ControlPanelViewStateCopyWithImpl; @override @useResult $Res call({ - UserEntity? loggedUser, List devices, DeviceEntity? selectedDevice, List positions, PositionEntity? selectedPosition, bool isLoading, String errorMessage + List devices, DeviceEntity? selectedDevice, List positions, PositionEntity? selectedPosition, bool isLoading, String errorMessage }); -@override $UserEntityCopyWith<$Res>? get loggedUser;@override $DeviceEntityCopyWith<$Res>? get selectedDevice;@override $PositionEntityCopyWith<$Res>? get selectedPosition; +@override $DeviceEntityCopyWith<$Res>? get selectedDevice;@override $PositionEntityCopyWith<$Res>? get selectedPosition; } /// @nodoc @@ -318,10 +304,9 @@ class __$ControlPanelViewStateCopyWithImpl<$Res> /// Create a copy of ControlPanelViewState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? loggedUser = freezed,Object? devices = null,Object? selectedDevice = freezed,Object? positions = null,Object? selectedPosition = freezed,Object? isLoading = null,Object? errorMessage = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? devices = null,Object? selectedDevice = freezed,Object? positions = null,Object? selectedPosition = freezed,Object? isLoading = null,Object? errorMessage = null,}) { return _then(_ControlPanelViewState( -loggedUser: freezed == loggedUser ? _self.loggedUser : loggedUser // ignore: cast_nullable_to_non_nullable -as UserEntity?,devices: null == devices ? _self._devices : devices // ignore: cast_nullable_to_non_nullable +devices: null == devices ? _self._devices : devices // ignore: cast_nullable_to_non_nullable as List,selectedDevice: freezed == selectedDevice ? _self.selectedDevice : selectedDevice // ignore: cast_nullable_to_non_nullable as DeviceEntity?,positions: null == positions ? _self._positions : positions // ignore: cast_nullable_to_non_nullable as List,selectedPosition: freezed == selectedPosition ? _self.selectedPosition : selectedPosition // ignore: cast_nullable_to_non_nullable @@ -335,18 +320,6 @@ as String, /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') -$UserEntityCopyWith<$Res>? get loggedUser { - if (_self.loggedUser == null) { - return null; - } - - return $UserEntityCopyWith<$Res>(_self.loggedUser!, (value) { - return _then(_self.copyWith(loggedUser: value)); - }); -}/// Create a copy of ControlPanelViewState -/// with the given fields replaced by the non-null parameter values. -@override -@pragma('vm:prefer-inline') $DeviceEntityCopyWith<$Res>? get selectedDevice { if (_self.selectedDevice == null) { return null; diff --git a/modules/legacy/modules/control_panel/lib/src/shared/widgets/device_map.dart b/modules/legacy/modules/control_panel/lib/src/shared/widgets/device_map.dart index 27f295a5..658287e1 100644 --- a/modules/legacy/modules/control_panel/lib/src/shared/widgets/device_map.dart +++ b/modules/legacy/modules/control_panel/lib/src/shared/widgets/device_map.dart @@ -17,11 +17,13 @@ const _tileServerUrl = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png'; class DeviceMap extends ConsumerStatefulWidget { final PositionEntity? selectedPosition; final DeviceEntity? selectedDevice; + final double markerSize; const DeviceMap({ super.key, required this.selectedPosition, required this.selectedDevice, + this.markerSize = 80, }); @override @@ -34,7 +36,7 @@ class _DeviceMapState extends ConsumerState { @override void initState() { super.initState(); - _mapController = MapControllerImpl(); + _mapController = MapController(); } @override @@ -87,13 +89,13 @@ class _DeviceMapState extends ConsumerState { widget.selectedPosition!.latitude, widget.selectedPosition!.longitude, ), - width: 200, - height: 145, + width: widget.markerSize * 2.5, + height: widget.markerSize * 1.8, child: Align( alignment: Alignment.topCenter, child: SvgPicture.asset( 'assets/shared/images/location.svg', - height: 80, + height: widget.markerSize, ), ), rotate: true, @@ -154,42 +156,44 @@ class LocationBanner extends ConsumerWidget { size: SizeUtils.getByScreen(small: 40, big: 38), color: theme.getColorFor(ThemeCode.legacyPrimary), ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox( - width: SizeUtils.getByScreen(small: 250, big: 248), - child: Text( + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( addressText, overflow: TextOverflow.ellipsis, ), - ), - Row( - children: [ - Text( - dateText, - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 12, big: 11), + Row( + children: [ + Flexible( + child: Text( + dateText, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11), + ), + overflow: TextOverflow.ellipsis, + ), ), - ), - if (position.networks.isNotEmpty) + if (position.networks.isNotEmpty) + Text( + ' | ${position.networks.first.signal}', + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11), + ), + ), + Icon(batteryIcon), Text( - ' | ${position.networks.first.signal}', + '$battery%', style: TextStyle( fontSize: SizeUtils.getByScreen(small: 12, big: 11), ), ), - Icon(batteryIcon), - Text( - '$battery%', - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 12, big: 11), - ), - ), - ], - ), - ], + ], + ), + ], + ), ), ], ), diff --git a/modules/legacy/modules/device_management/lib/device_management.dart b/modules/legacy/modules/device_management/lib/device_management.dart index d83a3543..e8fa9498 100644 --- a/modules/legacy/modules/device_management/lib/device_management.dart +++ b/modules/legacy/modules/device_management/lib/device_management.dart @@ -2,6 +2,11 @@ library functions; export 'src/features/device_management/device_management_builder.dart'; export 'src/features/contacts/contacts_builder.dart'; +export 'src/features/contacts/edit_contact_builder.dart'; +export 'src/features/scheduled_activities/scheduled_activities_builder.dart'; export 'src/features/remote_connection/remote_connection_builder.dart'; export 'src/features/locate_device/locate_device_builder.dart'; -export 'src/features/rewards/rewards_builder.dart'; \ No newline at end of file +export 'src/features/health/health_builder.dart'; +export 'src/features/rewards/rewards_builder.dart'; +export 'src/features/activity_meter/activity_meter_builder.dart'; +export 'src/features/apps_use/apps_use_builder.dart'; \ No newline at end of file diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/app_usage_times_remote_datasource.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/app_usage_times_remote_datasource.dart new file mode 100644 index 00000000..b612e306 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/app_usage_times_remote_datasource.dart @@ -0,0 +1,8 @@ +import '../models/get_app_usage_times_response_model.dart'; + +abstract class AppUsageTimesRemoteDatasource { + Future getAppUsageTimes({ + required String identificator, + Map queryParameters = const {}, + }); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/app_usage_times_remote_datasource_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/app_usage_times_remote_datasource_impl.dart new file mode 100644 index 00000000..87f02289 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/app_usage_times_remote_datasource_impl.dart @@ -0,0 +1,40 @@ +import 'package:dio/dio.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import '../models/get_app_usage_times_response_model.dart'; +import 'app_usage_times_remote_datasource.dart'; + +class AppUsageTimesRemoteDatasourceImpl + implements AppUsageTimesRemoteDatasource { + AppUsageTimesRemoteDatasourceImpl(this._repository); + + final QuestiaRepository _repository; + + @override + Future getAppUsageTimes({ + required String identificator, + Map queryParameters = const {}, + }) async { + try { + final response = await _repository.get>( + '/devices/identificator/$identificator/app-usage-times', + queryParameters: queryParameters, + ); + + final data = response.data; + if (data == null || data.isEmpty) { + throw Exception( + 'Empty response from /devices/identificator/$identificator/app-usage-times', + ); + } + + return GetAppUsageTimesResponseModel.fromJson(data); + } on DioException catch (error) { + throw mapDioError( + error, + defaultMessage: 'Error getting app usage times', + ); + } + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/contacts_remote_datasource.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/contacts_remote_datasource.dart index f444a599..c89c065b 100644 --- a/modules/legacy/modules/device_management/lib/src/core/data/datasources/contacts_remote_datasource.dart +++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/contacts_remote_datasource.dart @@ -1,14 +1,19 @@ -import 'package:device_management/src/core/data/models/create_contact_request_model.dart'; -import 'package:device_management/src/core/data/models/get_contacts_response_model.dart'; - +import '../models/create_contact_request_model.dart'; +import '../models/get_contacts_response_model.dart'; import '../models/update_contact_request_model.dart'; abstract class ContactsRemoteDatasource { Future getContacts({required String userId}); - Future updateContact({required String userId, required UpdateContactRequestModel request}); + Future updateContact({required UpdateContactRequestModel request}); - Future createContact({required ContactRequestModel request}); + Future createContact({required CreateContactRequestModel request}); Future deleteContact({required String contactId}); + + Future syncContactsToDevice({ + required String userId, + required String deviceId, + required List> contacts, + }); } diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/contacts_remote_datasource_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/contacts_remote_datasource_impl.dart index 1940c051..5e379703 100644 --- a/modules/legacy/modules/device_management/lib/src/core/data/datasources/contacts_remote_datasource_impl.dart +++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/contacts_remote_datasource_impl.dart @@ -1,8 +1,8 @@ -import 'package:device_management/src/core/data/models/create_contact_request_model.dart'; import 'package:dio/dio.dart'; import 'package:legacy_shared/legacy_shared.dart'; import 'package:sf_infrastructure/sf_infrastructure.dart'; +import '../models/create_contact_request_model.dart'; import '../models/get_contacts_response_model.dart'; import '../models/update_contact_request_model.dart'; import 'contacts_remote_datasource.dart'; @@ -24,45 +24,61 @@ class ContactsRemoteDatasourceImpl implements ContactsRemoteDatasource { throw Exception('Empty response from /users/:userId/contacts'); } - final model = GetContactsResponseModel.fromJson(data); - return model; + return GetContactsResponseModel.fromJson(data); } on DioException catch (error) { - throw mapDioError(error, defaultMessage: 'Error to get contacts'); + throw mapDioError(error, defaultMessage: 'Error getting contacts'); } } @override - Future updateContact({required String userId, required UpdateContactRequestModel request}) async { - final body = request.toJson(); - await safeCall( - () => _repository.put( - '/contacts/$userId', - body: body, - ), - 'Error in /contacts', - ); + Future updateContact({required UpdateContactRequestModel request}) async { + await safeCall( + () => _repository.put( + '/contacts/${request.id}', + body: request.toJson(), + ), + 'Error updating contact', + ); } @override - Future createContact({required ContactRequestModel request}) async { - final body = request.toJson(); - + Future createContact({required CreateContactRequestModel request}) async { await safeCall( () => _repository.post( '/contacts', - body: body, + body: request.toJson(), ), - 'Error in /contacts', + 'Error creating contact', ); } @override Future deleteContact({required String contactId}) async { await safeCall( - () => _repository.delete( - '/contacts/$contactId', - ), - 'Error in /contacts', + () => _repository.delete( + '/contacts/$contactId', + ), + 'Error deleting contact', + ); + } + + @override + Future syncContactsToDevice({ + required String userId, + required String deviceId, + required List> contacts, + }) async { + await safeCall( + () => _repository.post( + '/contact-lists', + body: { + 'userId': userId, + 'deviceId': deviceId, + 'type': 'secondary', + 'contacts': contacts, + }, + ), + 'Error syncing contacts to device', ); } } \ No newline at end of file diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/health_query_builder.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/health_query_builder.dart new file mode 100644 index 00000000..7d9c11da --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/health_query_builder.dart @@ -0,0 +1,73 @@ +import 'dart:convert'; + +enum OrderDirection { + asc('ASC'), + desc('DESC'); + + final String value; + const OrderDirection(this.value); +} + +class HealthQueryBuilder { + const HealthQueryBuilder._(); + + static Map build({ + required OrderDirection orderDirection, + int? page, + int? pageSize, + List? filters, + String orderField = 'occurredAt', + }) { + final orderBy = base64Encode( + utf8.encode('[{"field":"$orderField","order":"${orderDirection.value}"}]'), + ); + + final params = {'orderBy': orderBy}; + if (pageSize != null) params['pageSize'] = pageSize; + if (page != null) params['page'] = page; + + if (filters != null && filters.isNotEmpty) { + final json = filters + .map((f) => { + 'field': f.field, + 'operator': f.operator, + 'value': f.value, + }) + .toList(); + params['filters'] = base64Encode(utf8.encode(jsonEncode(json))); + } + + return params; + } + + static List timeRangeFilters({ + required DateTime start, + required DateTime end, + String field = 'occurredAt', + }) { + return [ + HealthFilter( + field: field, + operator: 'gte', + value: start.millisecondsSinceEpoch.toString(), + ), + HealthFilter( + field: field, + operator: 'lte', + value: end.millisecondsSinceEpoch.toString(), + ), + ]; + } +} + +class HealthFilter { + final String field; + final String operator; + final String value; + + const HealthFilter({ + required this.field, + required this.operator, + required this.value, + }); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/health_remote_datasource.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/health_remote_datasource.dart new file mode 100644 index 00000000..947a94d8 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/health_remote_datasource.dart @@ -0,0 +1,14 @@ +import '../models/get_heartbeats_response_model.dart'; +import '../models/get_oxygens_response_model.dart'; + +abstract class HealthRemoteDatasource { + Future getHeartbeats({ + required String identificator, + Map queryParameters = const {}, + }); + + Future getOxygens({ + required String identificator, + Map queryParameters = const {}, + }); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/health_remote_datasource_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/health_remote_datasource_impl.dart new file mode 100644 index 00000000..ae439264 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/health_remote_datasource_impl.dart @@ -0,0 +1,61 @@ +import 'package:dio/dio.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import '../models/get_heartbeats_response_model.dart'; +import '../models/get_oxygens_response_model.dart'; +import 'health_remote_datasource.dart'; + +class HealthRemoteDatasourceImpl implements HealthRemoteDatasource { + HealthRemoteDatasourceImpl(this._repository); + + final QuestiaRepository _repository; + + @override + Future getHeartbeats({ + required String identificator, + Map queryParameters = const {}, + }) async { + try { + final response = await _repository.get>( + '/devices/identificator/$identificator/heartbeats', + queryParameters: queryParameters, + ); + + final data = response.data; + if (data == null || data.isEmpty) { + throw Exception( + 'Empty response from /devices/identificator/$identificator/heartbeats', + ); + } + + return GetHeartbeatsResponseModel.fromJson(data); + } on DioException catch (error) { + throw mapDioError(error, defaultMessage: 'Error getting heartbeats'); + } + } + + @override + Future getOxygens({ + required String identificator, + Map queryParameters = const {}, + }) async { + try { + final response = await _repository.get>( + '/devices/identificator/$identificator/oxygens', + queryParameters: queryParameters, + ); + + final data = response.data; + if (data == null || data.isEmpty) { + throw Exception( + 'Empty response from /devices/identificator/$identificator/oxygens', + ); + } + + return GetOxygensResponseModel.fromJson(data); + } on DioException catch (error) { + throw mapDioError(error, defaultMessage: 'Error getting oxygens'); + } + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/scheduled_activities_remote_datasource.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/scheduled_activities_remote_datasource.dart new file mode 100644 index 00000000..8992e6a2 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/scheduled_activities_remote_datasource.dart @@ -0,0 +1,20 @@ +import '../models/create_scheduled_activity_request_model.dart'; +import '../models/get_scheduled_activities_response_model.dart'; +import '../models/update_scheduled_activity_request_model.dart'; + +abstract class ScheduledActivitiesRemoteDatasource { + Future getActivities({ + required String deviceId, + }); + + Future createActivity({ + required CreateScheduledActivityRequestModel request, + }); + + Future updateActivity({ + required String activityId, + required UpdateScheduledActivityRequestModel request, + }); + + Future deleteActivity({required String activityId}); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/scheduled_activities_remote_datasource_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/scheduled_activities_remote_datasource_impl.dart new file mode 100644 index 00000000..f0d2e29e --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/scheduled_activities_remote_datasource_impl.dart @@ -0,0 +1,77 @@ +import 'package:dio/dio.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import '../models/create_scheduled_activity_request_model.dart'; +import '../models/get_scheduled_activities_response_model.dart'; +import '../models/update_scheduled_activity_request_model.dart'; +import 'scheduled_activities_remote_datasource.dart'; + +class ScheduledActivitiesRemoteDatasourceImpl + implements ScheduledActivitiesRemoteDatasource { + ScheduledActivitiesRemoteDatasourceImpl(this._repository); + + final QuestiaRepository _repository; + + @override + Future getActivities({ + required String deviceId, + }) async { + try { + final response = await _repository.get>( + '/devices/$deviceId/scheduled-activities', + ); + + final data = response.data; + if (data == null || data.isEmpty) { + throw Exception( + 'Empty response from /devices/$deviceId/scheduled-activities', + ); + } + + return GetScheduledActivitiesResponseModel.fromJson(data); + } on DioException catch (error) { + throw mapDioError( + error, + defaultMessage: 'Error getting scheduled activities', + ); + } + } + + @override + Future createActivity({ + required CreateScheduledActivityRequestModel request, + }) async { + await safeCall( + () => _repository.post( + '/scheduled-activities', + body: request.toJson(), + ), + 'Error creating scheduled activity', + ); + } + + @override + Future updateActivity({ + required String activityId, + required UpdateScheduledActivityRequestModel request, + }) async { + await safeCall( + () => _repository.put( + '/scheduled-activities/$activityId', + body: request.toJson(), + ), + 'Error updating scheduled activity', + ); + } + + @override + Future deleteActivity({required String activityId}) async { + await safeCall( + () => _repository.delete( + '/scheduled-activities/$activityId', + ), + 'Error deleting scheduled activity', + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/steps_remote_datasource.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/steps_remote_datasource.dart new file mode 100644 index 00000000..dca382ac --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/steps_remote_datasource.dart @@ -0,0 +1,8 @@ +import '../models/get_steps_response_model.dart'; + +abstract class StepsRemoteDatasource { + Future getSteps({ + required String identificator, + Map queryParameters = const {}, + }); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/datasources/steps_remote_datasource_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/datasources/steps_remote_datasource_impl.dart new file mode 100644 index 00000000..5a65c63e --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/datasources/steps_remote_datasource_impl.dart @@ -0,0 +1,36 @@ +import 'package:dio/dio.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import '../models/get_steps_response_model.dart'; +import 'steps_remote_datasource.dart'; + +class StepsRemoteDatasourceImpl implements StepsRemoteDatasource { + StepsRemoteDatasourceImpl(this._repository); + + final QuestiaRepository _repository; + + @override + Future getSteps({ + required String identificator, + Map queryParameters = const {}, + }) async { + try { + final response = await _repository.get>( + '/devices/identificator/$identificator/steps', + queryParameters: queryParameters, + ); + + final data = response.data; + if (data == null || data.isEmpty) { + throw Exception( + 'Empty response from /devices/identificator/$identificator/steps', + ); + } + + return GetStepsResponseModel.fromJson(data); + } on DioException catch (error) { + throw mapDioError(error, defaultMessage: 'Error getting steps'); + } + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.dart index 05a5254d..7e435983 100644 --- a/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.dart +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.dart @@ -4,14 +4,14 @@ part 'create_contact_request_model.freezed.dart'; part 'create_contact_request_model.g.dart'; @freezed -abstract class ContactRequestModel with _$ContactRequestModel { - const factory ContactRequestModel({ +abstract class CreateContactRequestModel with _$CreateContactRequestModel { + const factory CreateContactRequestModel({ required String id, required String name, required String phone, String? userId, - }) = _ContactRequestModel; + }) = _CreateContactRequestModel; - factory ContactRequestModel.fromJson(Map json) => - _$ContactRequestModelFromJson(json); + factory CreateContactRequestModel.fromJson(Map json) => + _$CreateContactRequestModelFromJson(json); } \ No newline at end of file diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.freezed.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.freezed.dart index 70b9f2e1..2d4a9943 100644 --- a/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.freezed.dart +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.freezed.dart @@ -13,22 +13,22 @@ part of 'create_contact_request_model.dart'; T _$identity(T value) => value; /// @nodoc -mixin _$ContactRequestModel { +mixin _$CreateContactRequestModel { String get id; String get name; String get phone; String? get userId; -/// Create a copy of ContactRequestModel +/// Create a copy of CreateContactRequestModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') -$ContactRequestModelCopyWith get copyWith => _$ContactRequestModelCopyWithImpl(this as ContactRequestModel, _$identity); +$CreateContactRequestModelCopyWith get copyWith => _$CreateContactRequestModelCopyWithImpl(this as CreateContactRequestModel, _$identity); - /// Serializes this ContactRequestModel to a JSON map. + /// Serializes this CreateContactRequestModel to a JSON map. Map toJson(); @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is ContactRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.userId, userId) || other.userId == userId)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is CreateContactRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.userId, userId) || other.userId == userId)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -37,15 +37,15 @@ int get hashCode => Object.hash(runtimeType,id,name,phone,userId); @override String toString() { - return 'ContactRequestModel(id: $id, name: $name, phone: $phone, userId: $userId)'; + return 'CreateContactRequestModel(id: $id, name: $name, phone: $phone, userId: $userId)'; } } /// @nodoc -abstract mixin class $ContactRequestModelCopyWith<$Res> { - factory $ContactRequestModelCopyWith(ContactRequestModel value, $Res Function(ContactRequestModel) _then) = _$ContactRequestModelCopyWithImpl; +abstract mixin class $CreateContactRequestModelCopyWith<$Res> { + factory $CreateContactRequestModelCopyWith(CreateContactRequestModel value, $Res Function(CreateContactRequestModel) _then) = _$CreateContactRequestModelCopyWithImpl; @useResult $Res call({ String id, String name, String phone, String? userId @@ -56,14 +56,14 @@ $Res call({ } /// @nodoc -class _$ContactRequestModelCopyWithImpl<$Res> - implements $ContactRequestModelCopyWith<$Res> { - _$ContactRequestModelCopyWithImpl(this._self, this._then); +class _$CreateContactRequestModelCopyWithImpl<$Res> + implements $CreateContactRequestModelCopyWith<$Res> { + _$CreateContactRequestModelCopyWithImpl(this._self, this._then); - final ContactRequestModel _self; - final $Res Function(ContactRequestModel) _then; + final CreateContactRequestModel _self; + final $Res Function(CreateContactRequestModel) _then; -/// Create a copy of ContactRequestModel +/// Create a copy of CreateContactRequestModel /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? phone = null,Object? userId = freezed,}) { return _then(_self.copyWith( @@ -78,8 +78,8 @@ as String?, } -/// Adds pattern-matching-related methods to [ContactRequestModel]. -extension ContactRequestModelPatterns on ContactRequestModel { +/// Adds pattern-matching-related methods to [CreateContactRequestModel]. +extension CreateContactRequestModelPatterns on CreateContactRequestModel { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -92,10 +92,10 @@ extension ContactRequestModelPatterns on ContactRequestModel { /// } /// ``` -@optionalTypeArgs TResult maybeMap(TResult Function( _ContactRequestModel value)? $default,{required TResult orElse(),}){ +@optionalTypeArgs TResult maybeMap(TResult Function( _CreateContactRequestModel value)? $default,{required TResult orElse(),}){ final _that = this; switch (_that) { -case _ContactRequestModel() when $default != null: +case _CreateContactRequestModel() when $default != null: return $default(_that);case _: return orElse(); @@ -114,10 +114,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult map(TResult Function( _ContactRequestModel value) $default,){ +@optionalTypeArgs TResult map(TResult Function( _CreateContactRequestModel value) $default,){ final _that = this; switch (_that) { -case _ContactRequestModel(): +case _CreateContactRequestModel(): return $default(_that);case _: throw StateError('Unexpected subclass'); @@ -135,10 +135,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ContactRequestModel value)? $default,){ +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _CreateContactRequestModel value)? $default,){ final _that = this; switch (_that) { -case _ContactRequestModel() when $default != null: +case _CreateContactRequestModel() when $default != null: return $default(_that);case _: return null; @@ -158,7 +158,7 @@ return $default(_that);case _: @optionalTypeArgs TResult maybeWhen(TResult Function( String id, String name, String phone, String? userId)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { -case _ContactRequestModel() when $default != null: +case _CreateContactRequestModel() when $default != null: return $default(_that.id,_that.name,_that.phone,_that.userId);case _: return orElse(); @@ -179,7 +179,7 @@ return $default(_that.id,_that.name,_that.phone,_that.userId);case _: @optionalTypeArgs TResult when(TResult Function( String id, String name, String phone, String? userId) $default,) {final _that = this; switch (_that) { -case _ContactRequestModel(): +case _CreateContactRequestModel(): return $default(_that.id,_that.name,_that.phone,_that.userId);case _: throw StateError('Unexpected subclass'); @@ -199,7 +199,7 @@ return $default(_that.id,_that.name,_that.phone,_that.userId);case _: @optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String name, String phone, String? userId)? $default,) {final _that = this; switch (_that) { -case _ContactRequestModel() when $default != null: +case _CreateContactRequestModel() when $default != null: return $default(_that.id,_that.name,_that.phone,_that.userId);case _: return null; @@ -211,29 +211,29 @@ return $default(_that.id,_that.name,_that.phone,_that.userId);case _: /// @nodoc @JsonSerializable() -class _ContactRequestModel implements ContactRequestModel { - const _ContactRequestModel({required this.id, required this.name, required this.phone, this.userId}); - factory _ContactRequestModel.fromJson(Map json) => _$ContactRequestModelFromJson(json); +class _CreateContactRequestModel implements CreateContactRequestModel { + const _CreateContactRequestModel({required this.id, required this.name, required this.phone, this.userId}); + factory _CreateContactRequestModel.fromJson(Map json) => _$CreateContactRequestModelFromJson(json); @override final String id; @override final String name; @override final String phone; @override final String? userId; -/// Create a copy of ContactRequestModel +/// Create a copy of CreateContactRequestModel /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') -_$ContactRequestModelCopyWith<_ContactRequestModel> get copyWith => __$ContactRequestModelCopyWithImpl<_ContactRequestModel>(this, _$identity); +_$CreateContactRequestModelCopyWith<_CreateContactRequestModel> get copyWith => __$CreateContactRequestModelCopyWithImpl<_CreateContactRequestModel>(this, _$identity); @override Map toJson() { - return _$ContactRequestModelToJson(this, ); + return _$CreateContactRequestModelToJson(this, ); } @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _ContactRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.userId, userId) || other.userId == userId)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _CreateContactRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.userId, userId) || other.userId == userId)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -242,15 +242,15 @@ int get hashCode => Object.hash(runtimeType,id,name,phone,userId); @override String toString() { - return 'ContactRequestModel(id: $id, name: $name, phone: $phone, userId: $userId)'; + return 'CreateContactRequestModel(id: $id, name: $name, phone: $phone, userId: $userId)'; } } /// @nodoc -abstract mixin class _$ContactRequestModelCopyWith<$Res> implements $ContactRequestModelCopyWith<$Res> { - factory _$ContactRequestModelCopyWith(_ContactRequestModel value, $Res Function(_ContactRequestModel) _then) = __$ContactRequestModelCopyWithImpl; +abstract mixin class _$CreateContactRequestModelCopyWith<$Res> implements $CreateContactRequestModelCopyWith<$Res> { + factory _$CreateContactRequestModelCopyWith(_CreateContactRequestModel value, $Res Function(_CreateContactRequestModel) _then) = __$CreateContactRequestModelCopyWithImpl; @override @useResult $Res call({ String id, String name, String phone, String? userId @@ -261,17 +261,17 @@ $Res call({ } /// @nodoc -class __$ContactRequestModelCopyWithImpl<$Res> - implements _$ContactRequestModelCopyWith<$Res> { - __$ContactRequestModelCopyWithImpl(this._self, this._then); +class __$CreateContactRequestModelCopyWithImpl<$Res> + implements _$CreateContactRequestModelCopyWith<$Res> { + __$CreateContactRequestModelCopyWithImpl(this._self, this._then); - final _ContactRequestModel _self; - final $Res Function(_ContactRequestModel) _then; + final _CreateContactRequestModel _self; + final $Res Function(_CreateContactRequestModel) _then; -/// Create a copy of ContactRequestModel +/// Create a copy of CreateContactRequestModel /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? phone = null,Object? userId = freezed,}) { - return _then(_ContactRequestModel( + return _then(_CreateContactRequestModel( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.g.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.g.dart index cd82c505..0e9f36ca 100644 --- a/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.g.dart +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/create_contact_request_model.g.dart @@ -6,16 +6,17 @@ part of 'create_contact_request_model.dart'; // JsonSerializableGenerator // ************************************************************************** -_ContactRequestModel _$ContactRequestModelFromJson(Map json) => - _ContactRequestModel( - id: json['id'] as String, - name: json['name'] as String, - phone: json['phone'] as String, - userId: json['userId'] as String?, - ); +_CreateContactRequestModel _$CreateContactRequestModelFromJson( + Map json, +) => _CreateContactRequestModel( + id: json['id'] as String, + name: json['name'] as String, + phone: json['phone'] as String, + userId: json['userId'] as String?, +); -Map _$ContactRequestModelToJson( - _ContactRequestModel instance, +Map _$CreateContactRequestModelToJson( + _CreateContactRequestModel instance, ) => { 'id': instance.id, 'name': instance.name, diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/create_scheduled_activity_request_model.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/create_scheduled_activity_request_model.dart new file mode 100644 index 00000000..0bfd9490 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/create_scheduled_activity_request_model.dart @@ -0,0 +1,20 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'create_scheduled_activity_request_model.freezed.dart'; +part 'create_scheduled_activity_request_model.g.dart'; + +@freezed +abstract class CreateScheduledActivityRequestModel + with _$CreateScheduledActivityRequestModel { + const factory CreateScheduledActivityRequestModel({ + required String id, + required String deviceId, + required int weekDay, + required String name, + required String period, + }) = _CreateScheduledActivityRequestModel; + + factory CreateScheduledActivityRequestModel.fromJson( + Map json) => + _$CreateScheduledActivityRequestModelFromJson(json); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/create_scheduled_activity_request_model.freezed.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/create_scheduled_activity_request_model.freezed.dart new file mode 100644 index 00000000..2baad713 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/create_scheduled_activity_request_model.freezed.dart @@ -0,0 +1,289 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'create_scheduled_activity_request_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$CreateScheduledActivityRequestModel { + + String get id; String get deviceId; int get weekDay; String get name; String get period; +/// Create a copy of CreateScheduledActivityRequestModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CreateScheduledActivityRequestModelCopyWith get copyWith => _$CreateScheduledActivityRequestModelCopyWithImpl(this as CreateScheduledActivityRequestModel, _$identity); + + /// Serializes this CreateScheduledActivityRequestModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CreateScheduledActivityRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.weekDay, weekDay) || other.weekDay == weekDay)&&(identical(other.name, name) || other.name == name)&&(identical(other.period, period) || other.period == period)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,weekDay,name,period); + +@override +String toString() { + return 'CreateScheduledActivityRequestModel(id: $id, deviceId: $deviceId, weekDay: $weekDay, name: $name, period: $period)'; +} + + +} + +/// @nodoc +abstract mixin class $CreateScheduledActivityRequestModelCopyWith<$Res> { + factory $CreateScheduledActivityRequestModelCopyWith(CreateScheduledActivityRequestModel value, $Res Function(CreateScheduledActivityRequestModel) _then) = _$CreateScheduledActivityRequestModelCopyWithImpl; +@useResult +$Res call({ + String id, String deviceId, int weekDay, String name, String period +}); + + + + +} +/// @nodoc +class _$CreateScheduledActivityRequestModelCopyWithImpl<$Res> + implements $CreateScheduledActivityRequestModelCopyWith<$Res> { + _$CreateScheduledActivityRequestModelCopyWithImpl(this._self, this._then); + + final CreateScheduledActivityRequestModel _self; + final $Res Function(CreateScheduledActivityRequestModel) _then; + +/// Create a copy of CreateScheduledActivityRequestModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceId = null,Object? weekDay = null,Object? name = null,Object? period = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,weekDay: null == weekDay ? _self.weekDay : weekDay // ignore: cast_nullable_to_non_nullable +as int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,period: null == period ? _self.period : period // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [CreateScheduledActivityRequestModel]. +extension CreateScheduledActivityRequestModelPatterns on CreateScheduledActivityRequestModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _CreateScheduledActivityRequestModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _CreateScheduledActivityRequestModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _CreateScheduledActivityRequestModel value) $default,){ +final _that = this; +switch (_that) { +case _CreateScheduledActivityRequestModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _CreateScheduledActivityRequestModel value)? $default,){ +final _that = this; +switch (_that) { +case _CreateScheduledActivityRequestModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceId, int weekDay, String name, String period)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _CreateScheduledActivityRequestModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.weekDay,_that.name,_that.period);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceId, int weekDay, String name, String period) $default,) {final _that = this; +switch (_that) { +case _CreateScheduledActivityRequestModel(): +return $default(_that.id,_that.deviceId,_that.weekDay,_that.name,_that.period);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceId, int weekDay, String name, String period)? $default,) {final _that = this; +switch (_that) { +case _CreateScheduledActivityRequestModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.weekDay,_that.name,_that.period);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _CreateScheduledActivityRequestModel implements CreateScheduledActivityRequestModel { + const _CreateScheduledActivityRequestModel({required this.id, required this.deviceId, required this.weekDay, required this.name, required this.period}); + factory _CreateScheduledActivityRequestModel.fromJson(Map json) => _$CreateScheduledActivityRequestModelFromJson(json); + +@override final String id; +@override final String deviceId; +@override final int weekDay; +@override final String name; +@override final String period; + +/// Create a copy of CreateScheduledActivityRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$CreateScheduledActivityRequestModelCopyWith<_CreateScheduledActivityRequestModel> get copyWith => __$CreateScheduledActivityRequestModelCopyWithImpl<_CreateScheduledActivityRequestModel>(this, _$identity); + +@override +Map toJson() { + return _$CreateScheduledActivityRequestModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _CreateScheduledActivityRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.weekDay, weekDay) || other.weekDay == weekDay)&&(identical(other.name, name) || other.name == name)&&(identical(other.period, period) || other.period == period)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,weekDay,name,period); + +@override +String toString() { + return 'CreateScheduledActivityRequestModel(id: $id, deviceId: $deviceId, weekDay: $weekDay, name: $name, period: $period)'; +} + + +} + +/// @nodoc +abstract mixin class _$CreateScheduledActivityRequestModelCopyWith<$Res> implements $CreateScheduledActivityRequestModelCopyWith<$Res> { + factory _$CreateScheduledActivityRequestModelCopyWith(_CreateScheduledActivityRequestModel value, $Res Function(_CreateScheduledActivityRequestModel) _then) = __$CreateScheduledActivityRequestModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceId, int weekDay, String name, String period +}); + + + + +} +/// @nodoc +class __$CreateScheduledActivityRequestModelCopyWithImpl<$Res> + implements _$CreateScheduledActivityRequestModelCopyWith<$Res> { + __$CreateScheduledActivityRequestModelCopyWithImpl(this._self, this._then); + + final _CreateScheduledActivityRequestModel _self; + final $Res Function(_CreateScheduledActivityRequestModel) _then; + +/// Create a copy of CreateScheduledActivityRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceId = null,Object? weekDay = null,Object? name = null,Object? period = null,}) { + return _then(_CreateScheduledActivityRequestModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,weekDay: null == weekDay ? _self.weekDay : weekDay // ignore: cast_nullable_to_non_nullable +as int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,period: null == period ? _self.period : period // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/create_scheduled_activity_request_model.g.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/create_scheduled_activity_request_model.g.dart new file mode 100644 index 00000000..0549cf53 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/create_scheduled_activity_request_model.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'create_scheduled_activity_request_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_CreateScheduledActivityRequestModel +_$CreateScheduledActivityRequestModelFromJson(Map json) => + _CreateScheduledActivityRequestModel( + id: json['id'] as String, + deviceId: json['deviceId'] as String, + weekDay: (json['weekDay'] as num).toInt(), + name: json['name'] as String, + period: json['period'] as String, + ); + +Map _$CreateScheduledActivityRequestModelToJson( + _CreateScheduledActivityRequestModel instance, +) => { + 'id': instance.id, + 'deviceId': instance.deviceId, + 'weekDay': instance.weekDay, + 'name': instance.name, + 'period': instance.period, +}; diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_app_usage_times_response_model.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_app_usage_times_response_model.dart new file mode 100644 index 00000000..0b589479 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_app_usage_times_response_model.dart @@ -0,0 +1,55 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../domain/entities/app_usage_time_entity.dart'; + +part 'get_app_usage_times_response_model.freezed.dart'; +part 'get_app_usage_times_response_model.g.dart'; + +@freezed +abstract class GetAppUsageTimesResponseModel + with _$GetAppUsageTimesResponseModel { + const factory GetAppUsageTimesResponseModel({ + required int total, + required List items, + required int page, + required int pages, + }) = _GetAppUsageTimesResponseModel; + + factory GetAppUsageTimesResponseModel.fromJson(Map json) => + _$GetAppUsageTimesResponseModelFromJson(json); +} + +@freezed +abstract class AppUsageTimeItemResponseModel + with _$AppUsageTimeItemResponseModel { + const factory AppUsageTimeItemResponseModel({ + required String id, + required String uid, + required String deviceIdentificator, + required String name, + required String startAt, + required int duration, + required int createdAt, + }) = _AppUsageTimeItemResponseModel; + + factory AppUsageTimeItemResponseModel.fromJson(Map json) => + _$AppUsageTimeItemResponseModelFromJson(json); +} + +extension AppUsageTimesResponseMapper on GetAppUsageTimesResponseModel { + List toEntity() { + return items + .map( + (item) => AppUsageTimeEntity( + id: item.id, + uid: item.uid, + deviceIdentificator: item.deviceIdentificator, + name: item.name, + startAt: item.startAt, + duration: item.duration, + createdAt: item.createdAt, + ), + ) + .toList(); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_app_usage_times_response_model.freezed.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_app_usage_times_response_model.freezed.dart new file mode 100644 index 00000000..e944682e --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_app_usage_times_response_model.freezed.dart @@ -0,0 +1,573 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'get_app_usage_times_response_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$GetAppUsageTimesResponseModel { + + int get total; List get items; int get page; int get pages; +/// Create a copy of GetAppUsageTimesResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$GetAppUsageTimesResponseModelCopyWith get copyWith => _$GetAppUsageTimesResponseModelCopyWithImpl(this as GetAppUsageTimesResponseModel, _$identity); + + /// Serializes this GetAppUsageTimesResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is GetAppUsageTimesResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other.items, items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(items),page,pages); + +@override +String toString() { + return 'GetAppUsageTimesResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class $GetAppUsageTimesResponseModelCopyWith<$Res> { + factory $GetAppUsageTimesResponseModelCopyWith(GetAppUsageTimesResponseModel value, $Res Function(GetAppUsageTimesResponseModel) _then) = _$GetAppUsageTimesResponseModelCopyWithImpl; +@useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class _$GetAppUsageTimesResponseModelCopyWithImpl<$Res> + implements $GetAppUsageTimesResponseModelCopyWith<$Res> { + _$GetAppUsageTimesResponseModelCopyWithImpl(this._self, this._then); + + final GetAppUsageTimesResponseModel _self; + final $Res Function(GetAppUsageTimesResponseModel) _then; + +/// Create a copy of GetAppUsageTimesResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_self.copyWith( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [GetAppUsageTimesResponseModel]. +extension GetAppUsageTimesResponseModelPatterns on GetAppUsageTimesResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _GetAppUsageTimesResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _GetAppUsageTimesResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _GetAppUsageTimesResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _GetAppUsageTimesResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _GetAppUsageTimesResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _GetAppUsageTimesResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int total, List items, int page, int pages)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _GetAppUsageTimesResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int total, List items, int page, int pages) $default,) {final _that = this; +switch (_that) { +case _GetAppUsageTimesResponseModel(): +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int total, List items, int page, int pages)? $default,) {final _that = this; +switch (_that) { +case _GetAppUsageTimesResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _GetAppUsageTimesResponseModel implements GetAppUsageTimesResponseModel { + const _GetAppUsageTimesResponseModel({required this.total, required final List items, required this.page, required this.pages}): _items = items; + factory _GetAppUsageTimesResponseModel.fromJson(Map json) => _$GetAppUsageTimesResponseModelFromJson(json); + +@override final int total; + final List _items; +@override List get items { + if (_items is EqualUnmodifiableListView) return _items; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_items); +} + +@override final int page; +@override final int pages; + +/// Create a copy of GetAppUsageTimesResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$GetAppUsageTimesResponseModelCopyWith<_GetAppUsageTimesResponseModel> get copyWith => __$GetAppUsageTimesResponseModelCopyWithImpl<_GetAppUsageTimesResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$GetAppUsageTimesResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetAppUsageTimesResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other._items, _items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(_items),page,pages); + +@override +String toString() { + return 'GetAppUsageTimesResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class _$GetAppUsageTimesResponseModelCopyWith<$Res> implements $GetAppUsageTimesResponseModelCopyWith<$Res> { + factory _$GetAppUsageTimesResponseModelCopyWith(_GetAppUsageTimesResponseModel value, $Res Function(_GetAppUsageTimesResponseModel) _then) = __$GetAppUsageTimesResponseModelCopyWithImpl; +@override @useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class __$GetAppUsageTimesResponseModelCopyWithImpl<$Res> + implements _$GetAppUsageTimesResponseModelCopyWith<$Res> { + __$GetAppUsageTimesResponseModelCopyWithImpl(this._self, this._then); + + final _GetAppUsageTimesResponseModel _self; + final $Res Function(_GetAppUsageTimesResponseModel) _then; + +/// Create a copy of GetAppUsageTimesResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_GetAppUsageTimesResponseModel( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + + +/// @nodoc +mixin _$AppUsageTimeItemResponseModel { + + String get id; String get uid; String get deviceIdentificator; String get name; String get startAt; int get duration; int get createdAt; +/// Create a copy of AppUsageTimeItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AppUsageTimeItemResponseModelCopyWith get copyWith => _$AppUsageTimeItemResponseModelCopyWithImpl(this as AppUsageTimeItemResponseModel, _$identity); + + /// Serializes this AppUsageTimeItemResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AppUsageTimeItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.uid, uid) || other.uid == uid)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.name, name) || other.name == name)&&(identical(other.startAt, startAt) || other.startAt == startAt)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,uid,deviceIdentificator,name,startAt,duration,createdAt); + +@override +String toString() { + return 'AppUsageTimeItemResponseModel(id: $id, uid: $uid, deviceIdentificator: $deviceIdentificator, name: $name, startAt: $startAt, duration: $duration, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class $AppUsageTimeItemResponseModelCopyWith<$Res> { + factory $AppUsageTimeItemResponseModelCopyWith(AppUsageTimeItemResponseModel value, $Res Function(AppUsageTimeItemResponseModel) _then) = _$AppUsageTimeItemResponseModelCopyWithImpl; +@useResult +$Res call({ + String id, String uid, String deviceIdentificator, String name, String startAt, int duration, int createdAt +}); + + + + +} +/// @nodoc +class _$AppUsageTimeItemResponseModelCopyWithImpl<$Res> + implements $AppUsageTimeItemResponseModelCopyWith<$Res> { + _$AppUsageTimeItemResponseModelCopyWithImpl(this._self, this._then); + + final AppUsageTimeItemResponseModel _self; + final $Res Function(AppUsageTimeItemResponseModel) _then; + +/// Create a copy of AppUsageTimeItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? uid = null,Object? deviceIdentificator = null,Object? name = null,Object? startAt = null,Object? duration = null,Object? createdAt = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,uid: null == uid ? _self.uid : uid // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,startAt: null == startAt ? _self.startAt : startAt // ignore: cast_nullable_to_non_nullable +as String,duration: null == duration ? _self.duration : duration // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [AppUsageTimeItemResponseModel]. +extension AppUsageTimeItemResponseModelPatterns on AppUsageTimeItemResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AppUsageTimeItemResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AppUsageTimeItemResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AppUsageTimeItemResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _AppUsageTimeItemResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AppUsageTimeItemResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _AppUsageTimeItemResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String uid, String deviceIdentificator, String name, String startAt, int duration, int createdAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AppUsageTimeItemResponseModel() when $default != null: +return $default(_that.id,_that.uid,_that.deviceIdentificator,_that.name,_that.startAt,_that.duration,_that.createdAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String uid, String deviceIdentificator, String name, String startAt, int duration, int createdAt) $default,) {final _that = this; +switch (_that) { +case _AppUsageTimeItemResponseModel(): +return $default(_that.id,_that.uid,_that.deviceIdentificator,_that.name,_that.startAt,_that.duration,_that.createdAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String uid, String deviceIdentificator, String name, String startAt, int duration, int createdAt)? $default,) {final _that = this; +switch (_that) { +case _AppUsageTimeItemResponseModel() when $default != null: +return $default(_that.id,_that.uid,_that.deviceIdentificator,_that.name,_that.startAt,_that.duration,_that.createdAt);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _AppUsageTimeItemResponseModel implements AppUsageTimeItemResponseModel { + const _AppUsageTimeItemResponseModel({required this.id, required this.uid, required this.deviceIdentificator, required this.name, required this.startAt, required this.duration, required this.createdAt}); + factory _AppUsageTimeItemResponseModel.fromJson(Map json) => _$AppUsageTimeItemResponseModelFromJson(json); + +@override final String id; +@override final String uid; +@override final String deviceIdentificator; +@override final String name; +@override final String startAt; +@override final int duration; +@override final int createdAt; + +/// Create a copy of AppUsageTimeItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AppUsageTimeItemResponseModelCopyWith<_AppUsageTimeItemResponseModel> get copyWith => __$AppUsageTimeItemResponseModelCopyWithImpl<_AppUsageTimeItemResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$AppUsageTimeItemResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppUsageTimeItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.uid, uid) || other.uid == uid)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.name, name) || other.name == name)&&(identical(other.startAt, startAt) || other.startAt == startAt)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,uid,deviceIdentificator,name,startAt,duration,createdAt); + +@override +String toString() { + return 'AppUsageTimeItemResponseModel(id: $id, uid: $uid, deviceIdentificator: $deviceIdentificator, name: $name, startAt: $startAt, duration: $duration, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$AppUsageTimeItemResponseModelCopyWith<$Res> implements $AppUsageTimeItemResponseModelCopyWith<$Res> { + factory _$AppUsageTimeItemResponseModelCopyWith(_AppUsageTimeItemResponseModel value, $Res Function(_AppUsageTimeItemResponseModel) _then) = __$AppUsageTimeItemResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String uid, String deviceIdentificator, String name, String startAt, int duration, int createdAt +}); + + + + +} +/// @nodoc +class __$AppUsageTimeItemResponseModelCopyWithImpl<$Res> + implements _$AppUsageTimeItemResponseModelCopyWith<$Res> { + __$AppUsageTimeItemResponseModelCopyWithImpl(this._self, this._then); + + final _AppUsageTimeItemResponseModel _self; + final $Res Function(_AppUsageTimeItemResponseModel) _then; + +/// Create a copy of AppUsageTimeItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? uid = null,Object? deviceIdentificator = null,Object? name = null,Object? startAt = null,Object? duration = null,Object? createdAt = null,}) { + return _then(_AppUsageTimeItemResponseModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,uid: null == uid ? _self.uid : uid // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,startAt: null == startAt ? _self.startAt : startAt // ignore: cast_nullable_to_non_nullable +as String,duration: null == duration ? _self.duration : duration // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_app_usage_times_response_model.g.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_app_usage_times_response_model.g.dart new file mode 100644 index 00000000..455cc4c1 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_app_usage_times_response_model.g.dart @@ -0,0 +1,54 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_app_usage_times_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_GetAppUsageTimesResponseModel _$GetAppUsageTimesResponseModelFromJson( + Map json, +) => _GetAppUsageTimesResponseModel( + total: (json['total'] as num).toInt(), + items: (json['items'] as List) + .map( + (e) => + AppUsageTimeItemResponseModel.fromJson(e as Map), + ) + .toList(), + page: (json['page'] as num).toInt(), + pages: (json['pages'] as num).toInt(), +); + +Map _$GetAppUsageTimesResponseModelToJson( + _GetAppUsageTimesResponseModel instance, +) => { + 'total': instance.total, + 'items': instance.items, + 'page': instance.page, + 'pages': instance.pages, +}; + +_AppUsageTimeItemResponseModel _$AppUsageTimeItemResponseModelFromJson( + Map json, +) => _AppUsageTimeItemResponseModel( + id: json['id'] as String, + uid: json['uid'] as String, + deviceIdentificator: json['deviceIdentificator'] as String, + name: json['name'] as String, + startAt: json['startAt'] as String, + duration: (json['duration'] as num).toInt(), + createdAt: (json['createdAt'] as num).toInt(), +); + +Map _$AppUsageTimeItemResponseModelToJson( + _AppUsageTimeItemResponseModel instance, +) => { + 'id': instance.id, + 'uid': instance.uid, + 'deviceIdentificator': instance.deviceIdentificator, + 'name': instance.name, + 'startAt': instance.startAt, + 'duration': instance.duration, + 'createdAt': instance.createdAt, +}; diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_heartbeats_response_model.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_heartbeats_response_model.dart new file mode 100644 index 00000000..bd4d1732 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_heartbeats_response_model.dart @@ -0,0 +1,53 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../../features/health/domain/entities/heartbeat_entity.dart'; + +part 'get_heartbeats_response_model.freezed.dart'; +part 'get_heartbeats_response_model.g.dart'; + +@freezed +abstract class GetHeartbeatsResponseModel with _$GetHeartbeatsResponseModel { + const factory GetHeartbeatsResponseModel({ + required int total, + required List items, + required int page, + required int pages, + }) = _GetHeartbeatsResponseModel; + + factory GetHeartbeatsResponseModel.fromJson(Map json) => + _$GetHeartbeatsResponseModelFromJson(json); +} + +@freezed +abstract class HeartbeatItemResponseModel with _$HeartbeatItemResponseModel { + const factory HeartbeatItemResponseModel({ + required String id, + required String deviceIdentificator, + required int heartbeats, + int? lowBloodPressure, + int? highBloodPressure, + required int occurredAt, + required int createdAt, + }) = _HeartbeatItemResponseModel; + + factory HeartbeatItemResponseModel.fromJson(Map json) => + _$HeartbeatItemResponseModelFromJson(json); +} + +extension HeartbeatsResponseMapper on GetHeartbeatsResponseModel { + List toEntity() { + return items + .map( + (item) => HeartbeatEntity( + id: item.id, + deviceIdentificator: item.deviceIdentificator, + heartbeats: item.heartbeats, + lowBloodPressure: item.lowBloodPressure, + highBloodPressure: item.highBloodPressure, + occurredAt: item.occurredAt, + createdAt: item.createdAt, + ), + ) + .toList(); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_heartbeats_response_model.freezed.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_heartbeats_response_model.freezed.dart new file mode 100644 index 00000000..f4fee390 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_heartbeats_response_model.freezed.dart @@ -0,0 +1,573 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'get_heartbeats_response_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$GetHeartbeatsResponseModel { + + int get total; List get items; int get page; int get pages; +/// Create a copy of GetHeartbeatsResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$GetHeartbeatsResponseModelCopyWith get copyWith => _$GetHeartbeatsResponseModelCopyWithImpl(this as GetHeartbeatsResponseModel, _$identity); + + /// Serializes this GetHeartbeatsResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is GetHeartbeatsResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other.items, items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(items),page,pages); + +@override +String toString() { + return 'GetHeartbeatsResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class $GetHeartbeatsResponseModelCopyWith<$Res> { + factory $GetHeartbeatsResponseModelCopyWith(GetHeartbeatsResponseModel value, $Res Function(GetHeartbeatsResponseModel) _then) = _$GetHeartbeatsResponseModelCopyWithImpl; +@useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class _$GetHeartbeatsResponseModelCopyWithImpl<$Res> + implements $GetHeartbeatsResponseModelCopyWith<$Res> { + _$GetHeartbeatsResponseModelCopyWithImpl(this._self, this._then); + + final GetHeartbeatsResponseModel _self; + final $Res Function(GetHeartbeatsResponseModel) _then; + +/// Create a copy of GetHeartbeatsResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_self.copyWith( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [GetHeartbeatsResponseModel]. +extension GetHeartbeatsResponseModelPatterns on GetHeartbeatsResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _GetHeartbeatsResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _GetHeartbeatsResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _GetHeartbeatsResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _GetHeartbeatsResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _GetHeartbeatsResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _GetHeartbeatsResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int total, List items, int page, int pages)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _GetHeartbeatsResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int total, List items, int page, int pages) $default,) {final _that = this; +switch (_that) { +case _GetHeartbeatsResponseModel(): +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int total, List items, int page, int pages)? $default,) {final _that = this; +switch (_that) { +case _GetHeartbeatsResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _GetHeartbeatsResponseModel implements GetHeartbeatsResponseModel { + const _GetHeartbeatsResponseModel({required this.total, required final List items, required this.page, required this.pages}): _items = items; + factory _GetHeartbeatsResponseModel.fromJson(Map json) => _$GetHeartbeatsResponseModelFromJson(json); + +@override final int total; + final List _items; +@override List get items { + if (_items is EqualUnmodifiableListView) return _items; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_items); +} + +@override final int page; +@override final int pages; + +/// Create a copy of GetHeartbeatsResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$GetHeartbeatsResponseModelCopyWith<_GetHeartbeatsResponseModel> get copyWith => __$GetHeartbeatsResponseModelCopyWithImpl<_GetHeartbeatsResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$GetHeartbeatsResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetHeartbeatsResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other._items, _items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(_items),page,pages); + +@override +String toString() { + return 'GetHeartbeatsResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class _$GetHeartbeatsResponseModelCopyWith<$Res> implements $GetHeartbeatsResponseModelCopyWith<$Res> { + factory _$GetHeartbeatsResponseModelCopyWith(_GetHeartbeatsResponseModel value, $Res Function(_GetHeartbeatsResponseModel) _then) = __$GetHeartbeatsResponseModelCopyWithImpl; +@override @useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class __$GetHeartbeatsResponseModelCopyWithImpl<$Res> + implements _$GetHeartbeatsResponseModelCopyWith<$Res> { + __$GetHeartbeatsResponseModelCopyWithImpl(this._self, this._then); + + final _GetHeartbeatsResponseModel _self; + final $Res Function(_GetHeartbeatsResponseModel) _then; + +/// Create a copy of GetHeartbeatsResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_GetHeartbeatsResponseModel( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + + +/// @nodoc +mixin _$HeartbeatItemResponseModel { + + String get id; String get deviceIdentificator; int get heartbeats; int? get lowBloodPressure; int? get highBloodPressure; int get occurredAt; int get createdAt; +/// Create a copy of HeartbeatItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$HeartbeatItemResponseModelCopyWith get copyWith => _$HeartbeatItemResponseModelCopyWithImpl(this as HeartbeatItemResponseModel, _$identity); + + /// Serializes this HeartbeatItemResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is HeartbeatItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.heartbeats, heartbeats) || other.heartbeats == heartbeats)&&(identical(other.lowBloodPressure, lowBloodPressure) || other.lowBloodPressure == lowBloodPressure)&&(identical(other.highBloodPressure, highBloodPressure) || other.highBloodPressure == highBloodPressure)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,heartbeats,lowBloodPressure,highBloodPressure,occurredAt,createdAt); + +@override +String toString() { + return 'HeartbeatItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, heartbeats: $heartbeats, lowBloodPressure: $lowBloodPressure, highBloodPressure: $highBloodPressure, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class $HeartbeatItemResponseModelCopyWith<$Res> { + factory $HeartbeatItemResponseModelCopyWith(HeartbeatItemResponseModel value, $Res Function(HeartbeatItemResponseModel) _then) = _$HeartbeatItemResponseModelCopyWithImpl; +@useResult +$Res call({ + String id, String deviceIdentificator, int heartbeats, int? lowBloodPressure, int? highBloodPressure, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class _$HeartbeatItemResponseModelCopyWithImpl<$Res> + implements $HeartbeatItemResponseModelCopyWith<$Res> { + _$HeartbeatItemResponseModelCopyWithImpl(this._self, this._then); + + final HeartbeatItemResponseModel _self; + final $Res Function(HeartbeatItemResponseModel) _then; + +/// Create a copy of HeartbeatItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceIdentificator = null,Object? heartbeats = null,Object? lowBloodPressure = freezed,Object? highBloodPressure = freezed,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,heartbeats: null == heartbeats ? _self.heartbeats : heartbeats // ignore: cast_nullable_to_non_nullable +as int,lowBloodPressure: freezed == lowBloodPressure ? _self.lowBloodPressure : lowBloodPressure // ignore: cast_nullable_to_non_nullable +as int?,highBloodPressure: freezed == highBloodPressure ? _self.highBloodPressure : highBloodPressure // ignore: cast_nullable_to_non_nullable +as int?,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [HeartbeatItemResponseModel]. +extension HeartbeatItemResponseModelPatterns on HeartbeatItemResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _HeartbeatItemResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _HeartbeatItemResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _HeartbeatItemResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _HeartbeatItemResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _HeartbeatItemResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _HeartbeatItemResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceIdentificator, int heartbeats, int? lowBloodPressure, int? highBloodPressure, int occurredAt, int createdAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _HeartbeatItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.heartbeats,_that.lowBloodPressure,_that.highBloodPressure,_that.occurredAt,_that.createdAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceIdentificator, int heartbeats, int? lowBloodPressure, int? highBloodPressure, int occurredAt, int createdAt) $default,) {final _that = this; +switch (_that) { +case _HeartbeatItemResponseModel(): +return $default(_that.id,_that.deviceIdentificator,_that.heartbeats,_that.lowBloodPressure,_that.highBloodPressure,_that.occurredAt,_that.createdAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceIdentificator, int heartbeats, int? lowBloodPressure, int? highBloodPressure, int occurredAt, int createdAt)? $default,) {final _that = this; +switch (_that) { +case _HeartbeatItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.heartbeats,_that.lowBloodPressure,_that.highBloodPressure,_that.occurredAt,_that.createdAt);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _HeartbeatItemResponseModel implements HeartbeatItemResponseModel { + const _HeartbeatItemResponseModel({required this.id, required this.deviceIdentificator, required this.heartbeats, this.lowBloodPressure, this.highBloodPressure, required this.occurredAt, required this.createdAt}); + factory _HeartbeatItemResponseModel.fromJson(Map json) => _$HeartbeatItemResponseModelFromJson(json); + +@override final String id; +@override final String deviceIdentificator; +@override final int heartbeats; +@override final int? lowBloodPressure; +@override final int? highBloodPressure; +@override final int occurredAt; +@override final int createdAt; + +/// Create a copy of HeartbeatItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$HeartbeatItemResponseModelCopyWith<_HeartbeatItemResponseModel> get copyWith => __$HeartbeatItemResponseModelCopyWithImpl<_HeartbeatItemResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$HeartbeatItemResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _HeartbeatItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.heartbeats, heartbeats) || other.heartbeats == heartbeats)&&(identical(other.lowBloodPressure, lowBloodPressure) || other.lowBloodPressure == lowBloodPressure)&&(identical(other.highBloodPressure, highBloodPressure) || other.highBloodPressure == highBloodPressure)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,heartbeats,lowBloodPressure,highBloodPressure,occurredAt,createdAt); + +@override +String toString() { + return 'HeartbeatItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, heartbeats: $heartbeats, lowBloodPressure: $lowBloodPressure, highBloodPressure: $highBloodPressure, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$HeartbeatItemResponseModelCopyWith<$Res> implements $HeartbeatItemResponseModelCopyWith<$Res> { + factory _$HeartbeatItemResponseModelCopyWith(_HeartbeatItemResponseModel value, $Res Function(_HeartbeatItemResponseModel) _then) = __$HeartbeatItemResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceIdentificator, int heartbeats, int? lowBloodPressure, int? highBloodPressure, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class __$HeartbeatItemResponseModelCopyWithImpl<$Res> + implements _$HeartbeatItemResponseModelCopyWith<$Res> { + __$HeartbeatItemResponseModelCopyWithImpl(this._self, this._then); + + final _HeartbeatItemResponseModel _self; + final $Res Function(_HeartbeatItemResponseModel) _then; + +/// Create a copy of HeartbeatItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceIdentificator = null,Object? heartbeats = null,Object? lowBloodPressure = freezed,Object? highBloodPressure = freezed,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_HeartbeatItemResponseModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,heartbeats: null == heartbeats ? _self.heartbeats : heartbeats // ignore: cast_nullable_to_non_nullable +as int,lowBloodPressure: freezed == lowBloodPressure ? _self.lowBloodPressure : lowBloodPressure // ignore: cast_nullable_to_non_nullable +as int?,highBloodPressure: freezed == highBloodPressure ? _self.highBloodPressure : highBloodPressure // ignore: cast_nullable_to_non_nullable +as int?,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_heartbeats_response_model.g.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_heartbeats_response_model.g.dart new file mode 100644 index 00000000..39bdb168 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_heartbeats_response_model.g.dart @@ -0,0 +1,53 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_heartbeats_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_GetHeartbeatsResponseModel _$GetHeartbeatsResponseModelFromJson( + Map json, +) => _GetHeartbeatsResponseModel( + total: (json['total'] as num).toInt(), + items: (json['items'] as List) + .map( + (e) => HeartbeatItemResponseModel.fromJson(e as Map), + ) + .toList(), + page: (json['page'] as num).toInt(), + pages: (json['pages'] as num).toInt(), +); + +Map _$GetHeartbeatsResponseModelToJson( + _GetHeartbeatsResponseModel instance, +) => { + 'total': instance.total, + 'items': instance.items, + 'page': instance.page, + 'pages': instance.pages, +}; + +_HeartbeatItemResponseModel _$HeartbeatItemResponseModelFromJson( + Map json, +) => _HeartbeatItemResponseModel( + id: json['id'] as String, + deviceIdentificator: json['deviceIdentificator'] as String, + heartbeats: (json['heartbeats'] as num).toInt(), + lowBloodPressure: (json['lowBloodPressure'] as num?)?.toInt(), + highBloodPressure: (json['highBloodPressure'] as num?)?.toInt(), + occurredAt: (json['occurredAt'] as num).toInt(), + createdAt: (json['createdAt'] as num).toInt(), +); + +Map _$HeartbeatItemResponseModelToJson( + _HeartbeatItemResponseModel instance, +) => { + 'id': instance.id, + 'deviceIdentificator': instance.deviceIdentificator, + 'heartbeats': instance.heartbeats, + 'lowBloodPressure': instance.lowBloodPressure, + 'highBloodPressure': instance.highBloodPressure, + 'occurredAt': instance.occurredAt, + 'createdAt': instance.createdAt, +}; diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_oxygens_response_model.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_oxygens_response_model.dart new file mode 100644 index 00000000..d517457f --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_oxygens_response_model.dart @@ -0,0 +1,49 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../../features/health/domain/entities/oxygen_entity.dart'; + +part 'get_oxygens_response_model.freezed.dart'; +part 'get_oxygens_response_model.g.dart'; + +@freezed +abstract class GetOxygensResponseModel with _$GetOxygensResponseModel { + const factory GetOxygensResponseModel({ + required int total, + required List items, + required int page, + required int pages, + }) = _GetOxygensResponseModel; + + factory GetOxygensResponseModel.fromJson(Map json) => + _$GetOxygensResponseModelFromJson(json); +} + +@freezed +abstract class OxygenItemResponseModel with _$OxygenItemResponseModel { + const factory OxygenItemResponseModel({ + required String id, + required String deviceIdentificator, + required int oxygen, + required int occurredAt, + required int createdAt, + }) = _OxygenItemResponseModel; + + factory OxygenItemResponseModel.fromJson(Map json) => + _$OxygenItemResponseModelFromJson(json); +} + +extension OxygensResponseMapper on GetOxygensResponseModel { + List toEntity() { + return items + .map( + (item) => OxygenEntity( + id: item.id, + deviceIdentificator: item.deviceIdentificator, + oxygen: item.oxygen, + occurredAt: item.occurredAt, + createdAt: item.createdAt, + ), + ) + .toList(); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_oxygens_response_model.freezed.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_oxygens_response_model.freezed.dart new file mode 100644 index 00000000..9cac8a47 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_oxygens_response_model.freezed.dart @@ -0,0 +1,567 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'get_oxygens_response_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$GetOxygensResponseModel { + + int get total; List get items; int get page; int get pages; +/// Create a copy of GetOxygensResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$GetOxygensResponseModelCopyWith get copyWith => _$GetOxygensResponseModelCopyWithImpl(this as GetOxygensResponseModel, _$identity); + + /// Serializes this GetOxygensResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is GetOxygensResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other.items, items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(items),page,pages); + +@override +String toString() { + return 'GetOxygensResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class $GetOxygensResponseModelCopyWith<$Res> { + factory $GetOxygensResponseModelCopyWith(GetOxygensResponseModel value, $Res Function(GetOxygensResponseModel) _then) = _$GetOxygensResponseModelCopyWithImpl; +@useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class _$GetOxygensResponseModelCopyWithImpl<$Res> + implements $GetOxygensResponseModelCopyWith<$Res> { + _$GetOxygensResponseModelCopyWithImpl(this._self, this._then); + + final GetOxygensResponseModel _self; + final $Res Function(GetOxygensResponseModel) _then; + +/// Create a copy of GetOxygensResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_self.copyWith( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [GetOxygensResponseModel]. +extension GetOxygensResponseModelPatterns on GetOxygensResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _GetOxygensResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _GetOxygensResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _GetOxygensResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _GetOxygensResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _GetOxygensResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _GetOxygensResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int total, List items, int page, int pages)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _GetOxygensResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int total, List items, int page, int pages) $default,) {final _that = this; +switch (_that) { +case _GetOxygensResponseModel(): +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int total, List items, int page, int pages)? $default,) {final _that = this; +switch (_that) { +case _GetOxygensResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _GetOxygensResponseModel implements GetOxygensResponseModel { + const _GetOxygensResponseModel({required this.total, required final List items, required this.page, required this.pages}): _items = items; + factory _GetOxygensResponseModel.fromJson(Map json) => _$GetOxygensResponseModelFromJson(json); + +@override final int total; + final List _items; +@override List get items { + if (_items is EqualUnmodifiableListView) return _items; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_items); +} + +@override final int page; +@override final int pages; + +/// Create a copy of GetOxygensResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$GetOxygensResponseModelCopyWith<_GetOxygensResponseModel> get copyWith => __$GetOxygensResponseModelCopyWithImpl<_GetOxygensResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$GetOxygensResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetOxygensResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other._items, _items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(_items),page,pages); + +@override +String toString() { + return 'GetOxygensResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class _$GetOxygensResponseModelCopyWith<$Res> implements $GetOxygensResponseModelCopyWith<$Res> { + factory _$GetOxygensResponseModelCopyWith(_GetOxygensResponseModel value, $Res Function(_GetOxygensResponseModel) _then) = __$GetOxygensResponseModelCopyWithImpl; +@override @useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class __$GetOxygensResponseModelCopyWithImpl<$Res> + implements _$GetOxygensResponseModelCopyWith<$Res> { + __$GetOxygensResponseModelCopyWithImpl(this._self, this._then); + + final _GetOxygensResponseModel _self; + final $Res Function(_GetOxygensResponseModel) _then; + +/// Create a copy of GetOxygensResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_GetOxygensResponseModel( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + + +/// @nodoc +mixin _$OxygenItemResponseModel { + + String get id; String get deviceIdentificator; int get oxygen; int get occurredAt; int get createdAt; +/// Create a copy of OxygenItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$OxygenItemResponseModelCopyWith get copyWith => _$OxygenItemResponseModelCopyWithImpl(this as OxygenItemResponseModel, _$identity); + + /// Serializes this OxygenItemResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is OxygenItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.oxygen, oxygen) || other.oxygen == oxygen)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,oxygen,occurredAt,createdAt); + +@override +String toString() { + return 'OxygenItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, oxygen: $oxygen, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class $OxygenItemResponseModelCopyWith<$Res> { + factory $OxygenItemResponseModelCopyWith(OxygenItemResponseModel value, $Res Function(OxygenItemResponseModel) _then) = _$OxygenItemResponseModelCopyWithImpl; +@useResult +$Res call({ + String id, String deviceIdentificator, int oxygen, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class _$OxygenItemResponseModelCopyWithImpl<$Res> + implements $OxygenItemResponseModelCopyWith<$Res> { + _$OxygenItemResponseModelCopyWithImpl(this._self, this._then); + + final OxygenItemResponseModel _self; + final $Res Function(OxygenItemResponseModel) _then; + +/// Create a copy of OxygenItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceIdentificator = null,Object? oxygen = null,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,oxygen: null == oxygen ? _self.oxygen : oxygen // ignore: cast_nullable_to_non_nullable +as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [OxygenItemResponseModel]. +extension OxygenItemResponseModelPatterns on OxygenItemResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _OxygenItemResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _OxygenItemResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _OxygenItemResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _OxygenItemResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _OxygenItemResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _OxygenItemResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceIdentificator, int oxygen, int occurredAt, int createdAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _OxygenItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.oxygen,_that.occurredAt,_that.createdAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceIdentificator, int oxygen, int occurredAt, int createdAt) $default,) {final _that = this; +switch (_that) { +case _OxygenItemResponseModel(): +return $default(_that.id,_that.deviceIdentificator,_that.oxygen,_that.occurredAt,_that.createdAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceIdentificator, int oxygen, int occurredAt, int createdAt)? $default,) {final _that = this; +switch (_that) { +case _OxygenItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.oxygen,_that.occurredAt,_that.createdAt);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _OxygenItemResponseModel implements OxygenItemResponseModel { + const _OxygenItemResponseModel({required this.id, required this.deviceIdentificator, required this.oxygen, required this.occurredAt, required this.createdAt}); + factory _OxygenItemResponseModel.fromJson(Map json) => _$OxygenItemResponseModelFromJson(json); + +@override final String id; +@override final String deviceIdentificator; +@override final int oxygen; +@override final int occurredAt; +@override final int createdAt; + +/// Create a copy of OxygenItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$OxygenItemResponseModelCopyWith<_OxygenItemResponseModel> get copyWith => __$OxygenItemResponseModelCopyWithImpl<_OxygenItemResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$OxygenItemResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _OxygenItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.oxygen, oxygen) || other.oxygen == oxygen)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,oxygen,occurredAt,createdAt); + +@override +String toString() { + return 'OxygenItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, oxygen: $oxygen, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$OxygenItemResponseModelCopyWith<$Res> implements $OxygenItemResponseModelCopyWith<$Res> { + factory _$OxygenItemResponseModelCopyWith(_OxygenItemResponseModel value, $Res Function(_OxygenItemResponseModel) _then) = __$OxygenItemResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceIdentificator, int oxygen, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class __$OxygenItemResponseModelCopyWithImpl<$Res> + implements _$OxygenItemResponseModelCopyWith<$Res> { + __$OxygenItemResponseModelCopyWithImpl(this._self, this._then); + + final _OxygenItemResponseModel _self; + final $Res Function(_OxygenItemResponseModel) _then; + +/// Create a copy of OxygenItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceIdentificator = null,Object? oxygen = null,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_OxygenItemResponseModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,oxygen: null == oxygen ? _self.oxygen : oxygen // ignore: cast_nullable_to_non_nullable +as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_oxygens_response_model.g.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_oxygens_response_model.g.dart new file mode 100644 index 00000000..2547f56a --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_oxygens_response_model.g.dart @@ -0,0 +1,47 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_oxygens_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_GetOxygensResponseModel _$GetOxygensResponseModelFromJson( + Map json, +) => _GetOxygensResponseModel( + total: (json['total'] as num).toInt(), + items: (json['items'] as List) + .map((e) => OxygenItemResponseModel.fromJson(e as Map)) + .toList(), + page: (json['page'] as num).toInt(), + pages: (json['pages'] as num).toInt(), +); + +Map _$GetOxygensResponseModelToJson( + _GetOxygensResponseModel instance, +) => { + 'total': instance.total, + 'items': instance.items, + 'page': instance.page, + 'pages': instance.pages, +}; + +_OxygenItemResponseModel _$OxygenItemResponseModelFromJson( + Map json, +) => _OxygenItemResponseModel( + id: json['id'] as String, + deviceIdentificator: json['deviceIdentificator'] as String, + oxygen: (json['oxygen'] as num).toInt(), + occurredAt: (json['occurredAt'] as num).toInt(), + createdAt: (json['createdAt'] as num).toInt(), +); + +Map _$OxygenItemResponseModelToJson( + _OxygenItemResponseModel instance, +) => { + 'id': instance.id, + 'deviceIdentificator': instance.deviceIdentificator, + 'oxygen': instance.oxygen, + 'occurredAt': instance.occurredAt, + 'createdAt': instance.createdAt, +}; diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_scheduled_activities_response_model.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_scheduled_activities_response_model.dart new file mode 100644 index 00000000..1d88c5bc --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_scheduled_activities_response_model.dart @@ -0,0 +1,55 @@ +import 'package:device_management/src/features/scheduled_activities/domain/entities/scheduled_activity_entity.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'get_scheduled_activities_response_model.freezed.dart'; +part 'get_scheduled_activities_response_model.g.dart'; + +@freezed +abstract class GetScheduledActivitiesResponseModel + with _$GetScheduledActivitiesResponseModel { + const factory GetScheduledActivitiesResponseModel({ + required int total, + required List items, + required int page, + required int pages, + }) = _GetScheduledActivitiesResponseModel; + + factory GetScheduledActivitiesResponseModel.fromJson( + Map json) => + _$GetScheduledActivitiesResponseModelFromJson(json); +} + +@freezed +abstract class ScheduledActivityItemResponseModel + with _$ScheduledActivityItemResponseModel { + const factory ScheduledActivityItemResponseModel({ + required String id, + required String deviceId, + required int weekDay, + required String name, + required String period, + required int createdAt, + int? updatedAt, + }) = _ScheduledActivityItemResponseModel; + + factory ScheduledActivityItemResponseModel.fromJson( + Map json) => + _$ScheduledActivityItemResponseModelFromJson(json); +} + +extension ScheduledActivitiesResponseMapper + on GetScheduledActivitiesResponseModel { + List toEntity() { + return items + .map((item) => ScheduledActivityEntity( + id: item.id, + deviceId: item.deviceId, + weekDay: item.weekDay, + name: item.name, + period: item.period, + createdAt: item.createdAt, + updatedAt: item.updatedAt, + )) + .toList(); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_scheduled_activities_response_model.freezed.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_scheduled_activities_response_model.freezed.dart new file mode 100644 index 00000000..24dbab44 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_scheduled_activities_response_model.freezed.dart @@ -0,0 +1,573 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'get_scheduled_activities_response_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$GetScheduledActivitiesResponseModel { + + int get total; List get items; int get page; int get pages; +/// Create a copy of GetScheduledActivitiesResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$GetScheduledActivitiesResponseModelCopyWith get copyWith => _$GetScheduledActivitiesResponseModelCopyWithImpl(this as GetScheduledActivitiesResponseModel, _$identity); + + /// Serializes this GetScheduledActivitiesResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is GetScheduledActivitiesResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other.items, items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(items),page,pages); + +@override +String toString() { + return 'GetScheduledActivitiesResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class $GetScheduledActivitiesResponseModelCopyWith<$Res> { + factory $GetScheduledActivitiesResponseModelCopyWith(GetScheduledActivitiesResponseModel value, $Res Function(GetScheduledActivitiesResponseModel) _then) = _$GetScheduledActivitiesResponseModelCopyWithImpl; +@useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class _$GetScheduledActivitiesResponseModelCopyWithImpl<$Res> + implements $GetScheduledActivitiesResponseModelCopyWith<$Res> { + _$GetScheduledActivitiesResponseModelCopyWithImpl(this._self, this._then); + + final GetScheduledActivitiesResponseModel _self; + final $Res Function(GetScheduledActivitiesResponseModel) _then; + +/// Create a copy of GetScheduledActivitiesResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_self.copyWith( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [GetScheduledActivitiesResponseModel]. +extension GetScheduledActivitiesResponseModelPatterns on GetScheduledActivitiesResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _GetScheduledActivitiesResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _GetScheduledActivitiesResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _GetScheduledActivitiesResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _GetScheduledActivitiesResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _GetScheduledActivitiesResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _GetScheduledActivitiesResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int total, List items, int page, int pages)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _GetScheduledActivitiesResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int total, List items, int page, int pages) $default,) {final _that = this; +switch (_that) { +case _GetScheduledActivitiesResponseModel(): +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int total, List items, int page, int pages)? $default,) {final _that = this; +switch (_that) { +case _GetScheduledActivitiesResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _GetScheduledActivitiesResponseModel implements GetScheduledActivitiesResponseModel { + const _GetScheduledActivitiesResponseModel({required this.total, required final List items, required this.page, required this.pages}): _items = items; + factory _GetScheduledActivitiesResponseModel.fromJson(Map json) => _$GetScheduledActivitiesResponseModelFromJson(json); + +@override final int total; + final List _items; +@override List get items { + if (_items is EqualUnmodifiableListView) return _items; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_items); +} + +@override final int page; +@override final int pages; + +/// Create a copy of GetScheduledActivitiesResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$GetScheduledActivitiesResponseModelCopyWith<_GetScheduledActivitiesResponseModel> get copyWith => __$GetScheduledActivitiesResponseModelCopyWithImpl<_GetScheduledActivitiesResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$GetScheduledActivitiesResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetScheduledActivitiesResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other._items, _items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(_items),page,pages); + +@override +String toString() { + return 'GetScheduledActivitiesResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class _$GetScheduledActivitiesResponseModelCopyWith<$Res> implements $GetScheduledActivitiesResponseModelCopyWith<$Res> { + factory _$GetScheduledActivitiesResponseModelCopyWith(_GetScheduledActivitiesResponseModel value, $Res Function(_GetScheduledActivitiesResponseModel) _then) = __$GetScheduledActivitiesResponseModelCopyWithImpl; +@override @useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class __$GetScheduledActivitiesResponseModelCopyWithImpl<$Res> + implements _$GetScheduledActivitiesResponseModelCopyWith<$Res> { + __$GetScheduledActivitiesResponseModelCopyWithImpl(this._self, this._then); + + final _GetScheduledActivitiesResponseModel _self; + final $Res Function(_GetScheduledActivitiesResponseModel) _then; + +/// Create a copy of GetScheduledActivitiesResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_GetScheduledActivitiesResponseModel( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + + +/// @nodoc +mixin _$ScheduledActivityItemResponseModel { + + String get id; String get deviceId; int get weekDay; String get name; String get period; int get createdAt; int? get updatedAt; +/// Create a copy of ScheduledActivityItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ScheduledActivityItemResponseModelCopyWith get copyWith => _$ScheduledActivityItemResponseModelCopyWithImpl(this as ScheduledActivityItemResponseModel, _$identity); + + /// Serializes this ScheduledActivityItemResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ScheduledActivityItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.weekDay, weekDay) || other.weekDay == weekDay)&&(identical(other.name, name) || other.name == name)&&(identical(other.period, period) || other.period == period)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,weekDay,name,period,createdAt,updatedAt); + +@override +String toString() { + return 'ScheduledActivityItemResponseModel(id: $id, deviceId: $deviceId, weekDay: $weekDay, name: $name, period: $period, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class $ScheduledActivityItemResponseModelCopyWith<$Res> { + factory $ScheduledActivityItemResponseModelCopyWith(ScheduledActivityItemResponseModel value, $Res Function(ScheduledActivityItemResponseModel) _then) = _$ScheduledActivityItemResponseModelCopyWithImpl; +@useResult +$Res call({ + String id, String deviceId, int weekDay, String name, String period, int createdAt, int? updatedAt +}); + + + + +} +/// @nodoc +class _$ScheduledActivityItemResponseModelCopyWithImpl<$Res> + implements $ScheduledActivityItemResponseModelCopyWith<$Res> { + _$ScheduledActivityItemResponseModelCopyWithImpl(this._self, this._then); + + final ScheduledActivityItemResponseModel _self; + final $Res Function(ScheduledActivityItemResponseModel) _then; + +/// Create a copy of ScheduledActivityItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceId = null,Object? weekDay = null,Object? name = null,Object? period = null,Object? createdAt = null,Object? updatedAt = freezed,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,weekDay: null == weekDay ? _self.weekDay : weekDay // ignore: cast_nullable_to_non_nullable +as int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,period: null == period ? _self.period : period // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [ScheduledActivityItemResponseModel]. +extension ScheduledActivityItemResponseModelPatterns on ScheduledActivityItemResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _ScheduledActivityItemResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _ScheduledActivityItemResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _ScheduledActivityItemResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _ScheduledActivityItemResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ScheduledActivityItemResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _ScheduledActivityItemResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceId, int weekDay, String name, String period, int createdAt, int? updatedAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _ScheduledActivityItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.weekDay,_that.name,_that.period,_that.createdAt,_that.updatedAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceId, int weekDay, String name, String period, int createdAt, int? updatedAt) $default,) {final _that = this; +switch (_that) { +case _ScheduledActivityItemResponseModel(): +return $default(_that.id,_that.deviceId,_that.weekDay,_that.name,_that.period,_that.createdAt,_that.updatedAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceId, int weekDay, String name, String period, int createdAt, int? updatedAt)? $default,) {final _that = this; +switch (_that) { +case _ScheduledActivityItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.weekDay,_that.name,_that.period,_that.createdAt,_that.updatedAt);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _ScheduledActivityItemResponseModel implements ScheduledActivityItemResponseModel { + const _ScheduledActivityItemResponseModel({required this.id, required this.deviceId, required this.weekDay, required this.name, required this.period, required this.createdAt, this.updatedAt}); + factory _ScheduledActivityItemResponseModel.fromJson(Map json) => _$ScheduledActivityItemResponseModelFromJson(json); + +@override final String id; +@override final String deviceId; +@override final int weekDay; +@override final String name; +@override final String period; +@override final int createdAt; +@override final int? updatedAt; + +/// Create a copy of ScheduledActivityItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ScheduledActivityItemResponseModelCopyWith<_ScheduledActivityItemResponseModel> get copyWith => __$ScheduledActivityItemResponseModelCopyWithImpl<_ScheduledActivityItemResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$ScheduledActivityItemResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ScheduledActivityItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.weekDay, weekDay) || other.weekDay == weekDay)&&(identical(other.name, name) || other.name == name)&&(identical(other.period, period) || other.period == period)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,weekDay,name,period,createdAt,updatedAt); + +@override +String toString() { + return 'ScheduledActivityItemResponseModel(id: $id, deviceId: $deviceId, weekDay: $weekDay, name: $name, period: $period, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$ScheduledActivityItemResponseModelCopyWith<$Res> implements $ScheduledActivityItemResponseModelCopyWith<$Res> { + factory _$ScheduledActivityItemResponseModelCopyWith(_ScheduledActivityItemResponseModel value, $Res Function(_ScheduledActivityItemResponseModel) _then) = __$ScheduledActivityItemResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceId, int weekDay, String name, String period, int createdAt, int? updatedAt +}); + + + + +} +/// @nodoc +class __$ScheduledActivityItemResponseModelCopyWithImpl<$Res> + implements _$ScheduledActivityItemResponseModelCopyWith<$Res> { + __$ScheduledActivityItemResponseModelCopyWithImpl(this._self, this._then); + + final _ScheduledActivityItemResponseModel _self; + final $Res Function(_ScheduledActivityItemResponseModel) _then; + +/// Create a copy of ScheduledActivityItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceId = null,Object? weekDay = null,Object? name = null,Object? period = null,Object? createdAt = null,Object? updatedAt = freezed,}) { + return _then(_ScheduledActivityItemResponseModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,weekDay: null == weekDay ? _self.weekDay : weekDay // ignore: cast_nullable_to_non_nullable +as int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,period: null == period ? _self.period : period // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_scheduled_activities_response_model.g.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_scheduled_activities_response_model.g.dart new file mode 100644 index 00000000..b8ae6dc2 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_scheduled_activities_response_model.g.dart @@ -0,0 +1,55 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_scheduled_activities_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_GetScheduledActivitiesResponseModel +_$GetScheduledActivitiesResponseModelFromJson(Map json) => + _GetScheduledActivitiesResponseModel( + total: (json['total'] as num).toInt(), + items: (json['items'] as List) + .map( + (e) => ScheduledActivityItemResponseModel.fromJson( + e as Map, + ), + ) + .toList(), + page: (json['page'] as num).toInt(), + pages: (json['pages'] as num).toInt(), + ); + +Map _$GetScheduledActivitiesResponseModelToJson( + _GetScheduledActivitiesResponseModel instance, +) => { + 'total': instance.total, + 'items': instance.items, + 'page': instance.page, + 'pages': instance.pages, +}; + +_ScheduledActivityItemResponseModel +_$ScheduledActivityItemResponseModelFromJson(Map json) => + _ScheduledActivityItemResponseModel( + id: json['id'] as String, + deviceId: json['deviceId'] as String, + weekDay: (json['weekDay'] as num).toInt(), + name: json['name'] as String, + period: json['period'] as String, + createdAt: (json['createdAt'] as num).toInt(), + updatedAt: (json['updatedAt'] as num?)?.toInt(), + ); + +Map _$ScheduledActivityItemResponseModelToJson( + _ScheduledActivityItemResponseModel instance, +) => { + 'id': instance.id, + 'deviceId': instance.deviceId, + 'weekDay': instance.weekDay, + 'name': instance.name, + 'period': instance.period, + 'createdAt': instance.createdAt, + 'updatedAt': instance.updatedAt, +}; diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_steps_response_model.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_steps_response_model.dart new file mode 100644 index 00000000..454d1921 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_steps_response_model.dart @@ -0,0 +1,49 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../domain/entities/steps_entity.dart'; + +part 'get_steps_response_model.freezed.dart'; +part 'get_steps_response_model.g.dart'; + +@freezed +abstract class GetStepsResponseModel with _$GetStepsResponseModel { + const factory GetStepsResponseModel({ + required int total, + required List items, + required int page, + required int pages, + }) = _GetStepsResponseModel; + + factory GetStepsResponseModel.fromJson(Map json) => + _$GetStepsResponseModelFromJson(json); +} + +@freezed +abstract class StepsItemResponseModel with _$StepsItemResponseModel { + const factory StepsItemResponseModel({ + required String id, + required String deviceIdentificator, + required int steps, + required int occurredAt, + required int createdAt, + }) = _StepsItemResponseModel; + + factory StepsItemResponseModel.fromJson(Map json) => + _$StepsItemResponseModelFromJson(json); +} + +extension StepsResponseMapper on GetStepsResponseModel { + List toEntity() { + return items + .map( + (item) => StepsEntity( + id: item.id, + deviceIdentificator: item.deviceIdentificator, + steps: item.steps, + occurredAt: item.occurredAt, + createdAt: item.createdAt, + ), + ) + .toList(); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_steps_response_model.freezed.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_steps_response_model.freezed.dart new file mode 100644 index 00000000..3549dfcf --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_steps_response_model.freezed.dart @@ -0,0 +1,567 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'get_steps_response_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$GetStepsResponseModel { + + int get total; List get items; int get page; int get pages; +/// Create a copy of GetStepsResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$GetStepsResponseModelCopyWith get copyWith => _$GetStepsResponseModelCopyWithImpl(this as GetStepsResponseModel, _$identity); + + /// Serializes this GetStepsResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is GetStepsResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other.items, items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(items),page,pages); + +@override +String toString() { + return 'GetStepsResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class $GetStepsResponseModelCopyWith<$Res> { + factory $GetStepsResponseModelCopyWith(GetStepsResponseModel value, $Res Function(GetStepsResponseModel) _then) = _$GetStepsResponseModelCopyWithImpl; +@useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class _$GetStepsResponseModelCopyWithImpl<$Res> + implements $GetStepsResponseModelCopyWith<$Res> { + _$GetStepsResponseModelCopyWithImpl(this._self, this._then); + + final GetStepsResponseModel _self; + final $Res Function(GetStepsResponseModel) _then; + +/// Create a copy of GetStepsResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_self.copyWith( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [GetStepsResponseModel]. +extension GetStepsResponseModelPatterns on GetStepsResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _GetStepsResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _GetStepsResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _GetStepsResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _GetStepsResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _GetStepsResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _GetStepsResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int total, List items, int page, int pages)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _GetStepsResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int total, List items, int page, int pages) $default,) {final _that = this; +switch (_that) { +case _GetStepsResponseModel(): +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int total, List items, int page, int pages)? $default,) {final _that = this; +switch (_that) { +case _GetStepsResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _GetStepsResponseModel implements GetStepsResponseModel { + const _GetStepsResponseModel({required this.total, required final List items, required this.page, required this.pages}): _items = items; + factory _GetStepsResponseModel.fromJson(Map json) => _$GetStepsResponseModelFromJson(json); + +@override final int total; + final List _items; +@override List get items { + if (_items is EqualUnmodifiableListView) return _items; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_items); +} + +@override final int page; +@override final int pages; + +/// Create a copy of GetStepsResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$GetStepsResponseModelCopyWith<_GetStepsResponseModel> get copyWith => __$GetStepsResponseModelCopyWithImpl<_GetStepsResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$GetStepsResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetStepsResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other._items, _items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(_items),page,pages); + +@override +String toString() { + return 'GetStepsResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class _$GetStepsResponseModelCopyWith<$Res> implements $GetStepsResponseModelCopyWith<$Res> { + factory _$GetStepsResponseModelCopyWith(_GetStepsResponseModel value, $Res Function(_GetStepsResponseModel) _then) = __$GetStepsResponseModelCopyWithImpl; +@override @useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class __$GetStepsResponseModelCopyWithImpl<$Res> + implements _$GetStepsResponseModelCopyWith<$Res> { + __$GetStepsResponseModelCopyWithImpl(this._self, this._then); + + final _GetStepsResponseModel _self; + final $Res Function(_GetStepsResponseModel) _then; + +/// Create a copy of GetStepsResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_GetStepsResponseModel( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + + +/// @nodoc +mixin _$StepsItemResponseModel { + + String get id; String get deviceIdentificator; int get steps; int get occurredAt; int get createdAt; +/// Create a copy of StepsItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$StepsItemResponseModelCopyWith get copyWith => _$StepsItemResponseModelCopyWithImpl(this as StepsItemResponseModel, _$identity); + + /// Serializes this StepsItemResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is StepsItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.steps, steps) || other.steps == steps)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,steps,occurredAt,createdAt); + +@override +String toString() { + return 'StepsItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, steps: $steps, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class $StepsItemResponseModelCopyWith<$Res> { + factory $StepsItemResponseModelCopyWith(StepsItemResponseModel value, $Res Function(StepsItemResponseModel) _then) = _$StepsItemResponseModelCopyWithImpl; +@useResult +$Res call({ + String id, String deviceIdentificator, int steps, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class _$StepsItemResponseModelCopyWithImpl<$Res> + implements $StepsItemResponseModelCopyWith<$Res> { + _$StepsItemResponseModelCopyWithImpl(this._self, this._then); + + final StepsItemResponseModel _self; + final $Res Function(StepsItemResponseModel) _then; + +/// Create a copy of StepsItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceIdentificator = null,Object? steps = null,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,steps: null == steps ? _self.steps : steps // ignore: cast_nullable_to_non_nullable +as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [StepsItemResponseModel]. +extension StepsItemResponseModelPatterns on StepsItemResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _StepsItemResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _StepsItemResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _StepsItemResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _StepsItemResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _StepsItemResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _StepsItemResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceIdentificator, int steps, int occurredAt, int createdAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _StepsItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.steps,_that.occurredAt,_that.createdAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceIdentificator, int steps, int occurredAt, int createdAt) $default,) {final _that = this; +switch (_that) { +case _StepsItemResponseModel(): +return $default(_that.id,_that.deviceIdentificator,_that.steps,_that.occurredAt,_that.createdAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceIdentificator, int steps, int occurredAt, int createdAt)? $default,) {final _that = this; +switch (_that) { +case _StepsItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.steps,_that.occurredAt,_that.createdAt);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _StepsItemResponseModel implements StepsItemResponseModel { + const _StepsItemResponseModel({required this.id, required this.deviceIdentificator, required this.steps, required this.occurredAt, required this.createdAt}); + factory _StepsItemResponseModel.fromJson(Map json) => _$StepsItemResponseModelFromJson(json); + +@override final String id; +@override final String deviceIdentificator; +@override final int steps; +@override final int occurredAt; +@override final int createdAt; + +/// Create a copy of StepsItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$StepsItemResponseModelCopyWith<_StepsItemResponseModel> get copyWith => __$StepsItemResponseModelCopyWithImpl<_StepsItemResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$StepsItemResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _StepsItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.steps, steps) || other.steps == steps)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,steps,occurredAt,createdAt); + +@override +String toString() { + return 'StepsItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, steps: $steps, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$StepsItemResponseModelCopyWith<$Res> implements $StepsItemResponseModelCopyWith<$Res> { + factory _$StepsItemResponseModelCopyWith(_StepsItemResponseModel value, $Res Function(_StepsItemResponseModel) _then) = __$StepsItemResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceIdentificator, int steps, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class __$StepsItemResponseModelCopyWithImpl<$Res> + implements _$StepsItemResponseModelCopyWith<$Res> { + __$StepsItemResponseModelCopyWithImpl(this._self, this._then); + + final _StepsItemResponseModel _self; + final $Res Function(_StepsItemResponseModel) _then; + +/// Create a copy of StepsItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceIdentificator = null,Object? steps = null,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_StepsItemResponseModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,steps: null == steps ? _self.steps : steps // ignore: cast_nullable_to_non_nullable +as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/get_steps_response_model.g.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/get_steps_response_model.g.dart new file mode 100644 index 00000000..39f727eb --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/get_steps_response_model.g.dart @@ -0,0 +1,47 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_steps_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_GetStepsResponseModel _$GetStepsResponseModelFromJson( + Map json, +) => _GetStepsResponseModel( + total: (json['total'] as num).toInt(), + items: (json['items'] as List) + .map((e) => StepsItemResponseModel.fromJson(e as Map)) + .toList(), + page: (json['page'] as num).toInt(), + pages: (json['pages'] as num).toInt(), +); + +Map _$GetStepsResponseModelToJson( + _GetStepsResponseModel instance, +) => { + 'total': instance.total, + 'items': instance.items, + 'page': instance.page, + 'pages': instance.pages, +}; + +_StepsItemResponseModel _$StepsItemResponseModelFromJson( + Map json, +) => _StepsItemResponseModel( + id: json['id'] as String, + deviceIdentificator: json['deviceIdentificator'] as String, + steps: (json['steps'] as num).toInt(), + occurredAt: (json['occurredAt'] as num).toInt(), + createdAt: (json['createdAt'] as num).toInt(), +); + +Map _$StepsItemResponseModelToJson( + _StepsItemResponseModel instance, +) => { + 'id': instance.id, + 'deviceIdentificator': instance.deviceIdentificator, + 'steps': instance.steps, + 'occurredAt': instance.occurredAt, + 'createdAt': instance.createdAt, +}; diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/update_scheduled_activity_request_model.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/update_scheduled_activity_request_model.dart new file mode 100644 index 00000000..e3008cd7 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/update_scheduled_activity_request_model.dart @@ -0,0 +1,18 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'update_scheduled_activity_request_model.freezed.dart'; +part 'update_scheduled_activity_request_model.g.dart'; + +@freezed +abstract class UpdateScheduledActivityRequestModel + with _$UpdateScheduledActivityRequestModel { + const factory UpdateScheduledActivityRequestModel({ + required String deviceId, + required String name, + required String period, + }) = _UpdateScheduledActivityRequestModel; + + factory UpdateScheduledActivityRequestModel.fromJson( + Map json) => + _$UpdateScheduledActivityRequestModelFromJson(json); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/update_scheduled_activity_request_model.freezed.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/update_scheduled_activity_request_model.freezed.dart new file mode 100644 index 00000000..9b90bcbf --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/update_scheduled_activity_request_model.freezed.dart @@ -0,0 +1,283 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'update_scheduled_activity_request_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$UpdateScheduledActivityRequestModel { + + String get deviceId; String get name; String get period; +/// Create a copy of UpdateScheduledActivityRequestModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$UpdateScheduledActivityRequestModelCopyWith get copyWith => _$UpdateScheduledActivityRequestModelCopyWithImpl(this as UpdateScheduledActivityRequestModel, _$identity); + + /// Serializes this UpdateScheduledActivityRequestModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is UpdateScheduledActivityRequestModel&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.name, name) || other.name == name)&&(identical(other.period, period) || other.period == period)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,deviceId,name,period); + +@override +String toString() { + return 'UpdateScheduledActivityRequestModel(deviceId: $deviceId, name: $name, period: $period)'; +} + + +} + +/// @nodoc +abstract mixin class $UpdateScheduledActivityRequestModelCopyWith<$Res> { + factory $UpdateScheduledActivityRequestModelCopyWith(UpdateScheduledActivityRequestModel value, $Res Function(UpdateScheduledActivityRequestModel) _then) = _$UpdateScheduledActivityRequestModelCopyWithImpl; +@useResult +$Res call({ + String deviceId, String name, String period +}); + + + + +} +/// @nodoc +class _$UpdateScheduledActivityRequestModelCopyWithImpl<$Res> + implements $UpdateScheduledActivityRequestModelCopyWith<$Res> { + _$UpdateScheduledActivityRequestModelCopyWithImpl(this._self, this._then); + + final UpdateScheduledActivityRequestModel _self; + final $Res Function(UpdateScheduledActivityRequestModel) _then; + +/// Create a copy of UpdateScheduledActivityRequestModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? deviceId = null,Object? name = null,Object? period = null,}) { + return _then(_self.copyWith( +deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,period: null == period ? _self.period : period // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [UpdateScheduledActivityRequestModel]. +extension UpdateScheduledActivityRequestModelPatterns on UpdateScheduledActivityRequestModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _UpdateScheduledActivityRequestModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _UpdateScheduledActivityRequestModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _UpdateScheduledActivityRequestModel value) $default,){ +final _that = this; +switch (_that) { +case _UpdateScheduledActivityRequestModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _UpdateScheduledActivityRequestModel value)? $default,){ +final _that = this; +switch (_that) { +case _UpdateScheduledActivityRequestModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String deviceId, String name, String period)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _UpdateScheduledActivityRequestModel() when $default != null: +return $default(_that.deviceId,_that.name,_that.period);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String deviceId, String name, String period) $default,) {final _that = this; +switch (_that) { +case _UpdateScheduledActivityRequestModel(): +return $default(_that.deviceId,_that.name,_that.period);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String deviceId, String name, String period)? $default,) {final _that = this; +switch (_that) { +case _UpdateScheduledActivityRequestModel() when $default != null: +return $default(_that.deviceId,_that.name,_that.period);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _UpdateScheduledActivityRequestModel implements UpdateScheduledActivityRequestModel { + const _UpdateScheduledActivityRequestModel({required this.deviceId, required this.name, required this.period}); + factory _UpdateScheduledActivityRequestModel.fromJson(Map json) => _$UpdateScheduledActivityRequestModelFromJson(json); + +@override final String deviceId; +@override final String name; +@override final String period; + +/// Create a copy of UpdateScheduledActivityRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$UpdateScheduledActivityRequestModelCopyWith<_UpdateScheduledActivityRequestModel> get copyWith => __$UpdateScheduledActivityRequestModelCopyWithImpl<_UpdateScheduledActivityRequestModel>(this, _$identity); + +@override +Map toJson() { + return _$UpdateScheduledActivityRequestModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _UpdateScheduledActivityRequestModel&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.name, name) || other.name == name)&&(identical(other.period, period) || other.period == period)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,deviceId,name,period); + +@override +String toString() { + return 'UpdateScheduledActivityRequestModel(deviceId: $deviceId, name: $name, period: $period)'; +} + + +} + +/// @nodoc +abstract mixin class _$UpdateScheduledActivityRequestModelCopyWith<$Res> implements $UpdateScheduledActivityRequestModelCopyWith<$Res> { + factory _$UpdateScheduledActivityRequestModelCopyWith(_UpdateScheduledActivityRequestModel value, $Res Function(_UpdateScheduledActivityRequestModel) _then) = __$UpdateScheduledActivityRequestModelCopyWithImpl; +@override @useResult +$Res call({ + String deviceId, String name, String period +}); + + + + +} +/// @nodoc +class __$UpdateScheduledActivityRequestModelCopyWithImpl<$Res> + implements _$UpdateScheduledActivityRequestModelCopyWith<$Res> { + __$UpdateScheduledActivityRequestModelCopyWithImpl(this._self, this._then); + + final _UpdateScheduledActivityRequestModel _self; + final $Res Function(_UpdateScheduledActivityRequestModel) _then; + +/// Create a copy of UpdateScheduledActivityRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? deviceId = null,Object? name = null,Object? period = null,}) { + return _then(_UpdateScheduledActivityRequestModel( +deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,period: null == period ? _self.period : period // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/core/data/models/update_scheduled_activity_request_model.g.dart b/modules/legacy/modules/device_management/lib/src/core/data/models/update_scheduled_activity_request_model.g.dart new file mode 100644 index 00000000..f143b279 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/models/update_scheduled_activity_request_model.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'update_scheduled_activity_request_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_UpdateScheduledActivityRequestModel +_$UpdateScheduledActivityRequestModelFromJson(Map json) => + _UpdateScheduledActivityRequestModel( + deviceId: json['deviceId'] as String, + name: json['name'] as String, + period: json['period'] as String, + ); + +Map _$UpdateScheduledActivityRequestModelToJson( + _UpdateScheduledActivityRequestModel instance, +) => { + 'deviceId': instance.deviceId, + 'name': instance.name, + 'period': instance.period, +}; diff --git a/modules/legacy/modules/device_management/lib/src/core/data/repositories/app_usage_times_repository_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/repositories/app_usage_times_repository_impl.dart new file mode 100644 index 00000000..da033878 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/repositories/app_usage_times_repository_impl.dart @@ -0,0 +1,22 @@ +import '../../domain/entities/app_usage_time_entity.dart'; +import '../../domain/repositories/app_usage_times_repository.dart'; +import '../datasources/app_usage_times_remote_datasource.dart'; +import '../models/get_app_usage_times_response_model.dart'; + +class AppUsageTimesRepositoryImpl implements AppUsageTimesRepository { + const AppUsageTimesRepositoryImpl(this._remote); + + final AppUsageTimesRemoteDatasource _remote; + + @override + Future> getAppUsageTimes({ + required String identificator, + Map queryParameters = const {}, + }) async { + final model = await _remote.getAppUsageTimes( + identificator: identificator, + queryParameters: queryParameters, + ); + return model.toEntity(); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/repositories/contacts_repository_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/repositories/contacts_repository_impl.dart index 52e4ce2b..8d582977 100644 --- a/modules/legacy/modules/device_management/lib/src/core/data/repositories/contacts_repository_impl.dart +++ b/modules/legacy/modules/device_management/lib/src/core/data/repositories/contacts_repository_impl.dart @@ -1,9 +1,8 @@ -import 'package:device_management/src/core/data/models/get_contacts_response_model.dart'; -import 'package:device_management/src/features/contacts/domain/entities/contact_entity.dart'; - +import '../../../features/contacts/domain/entities/contact_entity.dart'; import '../../domain/repositories/contacts_repository.dart'; import '../datasources/contacts_remote_datasource.dart'; import '../models/create_contact_request_model.dart'; +import '../models/get_contacts_response_model.dart'; import '../models/update_contact_request_model.dart'; class ContactsRepositoryImpl implements ContactsRepository { @@ -18,12 +17,12 @@ class ContactsRepositoryImpl implements ContactsRepository { } @override - Future updateContact({required String userId, required UpdateContactRequestModel request}) { - return _remote.updateContact(userId: userId, request: request); + Future updateContact({required UpdateContactRequestModel request}) { + return _remote.updateContact(request: request); } @override - Future createContact({required ContactRequestModel request}) { + Future createContact({required CreateContactRequestModel request}) { return _remote.createContact(request: request); } @@ -31,4 +30,19 @@ class ContactsRepositoryImpl implements ContactsRepository { Future deleteContact({required String contactId}) { return _remote.deleteContact(contactId: contactId); } -} \ No newline at end of file + + @override + Future syncContactsToDevice({ + required String userId, + required String deviceId, + required List contacts, + }) { + return _remote.syncContactsToDevice( + userId: userId, + deviceId: deviceId, + contacts: contacts + .map((c) => {'name': c.name, 'phone': c.phone}) + .toList(), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/repositories/health_repository_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/repositories/health_repository_impl.dart new file mode 100644 index 00000000..97f74a77 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/repositories/health_repository_impl.dart @@ -0,0 +1,36 @@ +import '../../../features/health/domain/entities/heartbeat_entity.dart'; +import '../../../features/health/domain/entities/oxygen_entity.dart'; +import '../../domain/repositories/health_repository.dart'; +import '../datasources/health_remote_datasource.dart'; +import '../models/get_heartbeats_response_model.dart'; +import '../models/get_oxygens_response_model.dart'; + +class HealthRepositoryImpl implements HealthRepository { + const HealthRepositoryImpl(this._remote); + + final HealthRemoteDatasource _remote; + + @override + Future> getHeartbeats({ + required String identificator, + Map queryParameters = const {}, + }) async { + final model = await _remote.getHeartbeats( + identificator: identificator, + queryParameters: queryParameters, + ); + return model.toEntity(); + } + + @override + Future> getOxygens({ + required String identificator, + Map queryParameters = const {}, + }) async { + final model = await _remote.getOxygens( + identificator: identificator, + queryParameters: queryParameters, + ); + return model.toEntity(); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/repositories/scheduled_activities_repository_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/repositories/scheduled_activities_repository_impl.dart new file mode 100644 index 00000000..99c7f85b --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/repositories/scheduled_activities_repository_impl.dart @@ -0,0 +1,41 @@ +import '../../../features/scheduled_activities/domain/entities/scheduled_activity_entity.dart'; +import '../../domain/repositories/scheduled_activities_repository.dart'; +import '../datasources/scheduled_activities_remote_datasource.dart'; +import '../models/create_scheduled_activity_request_model.dart'; +import '../models/get_scheduled_activities_response_model.dart'; +import '../models/update_scheduled_activity_request_model.dart'; + +class ScheduledActivitiesRepositoryImpl + implements ScheduledActivitiesRepository { + const ScheduledActivitiesRepositoryImpl(this._remote); + + final ScheduledActivitiesRemoteDatasource _remote; + + @override + Future> getActivities({ + required String deviceId, + }) async { + final model = await _remote.getActivities(deviceId: deviceId); + return model.toEntity(); + } + + @override + Future createActivity({ + required CreateScheduledActivityRequestModel request, + }) { + return _remote.createActivity(request: request); + } + + @override + Future updateActivity({ + required String activityId, + required UpdateScheduledActivityRequestModel request, + }) { + return _remote.updateActivity(activityId: activityId, request: request); + } + + @override + Future deleteActivity({required String activityId}) { + return _remote.deleteActivity(activityId: activityId); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/data/repositories/steps_repository_impl.dart b/modules/legacy/modules/device_management/lib/src/core/data/repositories/steps_repository_impl.dart new file mode 100644 index 00000000..4d150e69 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/data/repositories/steps_repository_impl.dart @@ -0,0 +1,22 @@ +import '../../domain/entities/steps_entity.dart'; +import '../../domain/repositories/steps_repository.dart'; +import '../datasources/steps_remote_datasource.dart'; +import '../models/get_steps_response_model.dart'; + +class StepsRepositoryImpl implements StepsRepository { + const StepsRepositoryImpl(this._remote); + + final StepsRemoteDatasource _remote; + + @override + Future> getSteps({ + required String identificator, + Map queryParameters = const {}, + }) async { + final model = await _remote.getSteps( + identificator: identificator, + queryParameters: queryParameters, + ); + return model.toEntity(); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/domain/entities/app_usage_time_entity.dart b/modules/legacy/modules/device_management/lib/src/core/domain/entities/app_usage_time_entity.dart new file mode 100644 index 00000000..c1642336 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/domain/entities/app_usage_time_entity.dart @@ -0,0 +1,16 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'app_usage_time_entity.freezed.dart'; + +@freezed +abstract class AppUsageTimeEntity with _$AppUsageTimeEntity { + const factory AppUsageTimeEntity({ + required String id, + required String uid, + required String deviceIdentificator, + required String name, + required String startAt, + required int duration, + required int createdAt, + }) = _AppUsageTimeEntity; +} diff --git a/modules/legacy/modules/device_management/lib/src/core/domain/entities/app_usage_time_entity.freezed.dart b/modules/legacy/modules/device_management/lib/src/core/domain/entities/app_usage_time_entity.freezed.dart new file mode 100644 index 00000000..3ea702e2 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/domain/entities/app_usage_time_entity.freezed.dart @@ -0,0 +1,289 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'app_usage_time_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$AppUsageTimeEntity { + + String get id; String get uid; String get deviceIdentificator; String get name; String get startAt; int get duration; int get createdAt; +/// Create a copy of AppUsageTimeEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AppUsageTimeEntityCopyWith get copyWith => _$AppUsageTimeEntityCopyWithImpl(this as AppUsageTimeEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AppUsageTimeEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.uid, uid) || other.uid == uid)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.name, name) || other.name == name)&&(identical(other.startAt, startAt) || other.startAt == startAt)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,uid,deviceIdentificator,name,startAt,duration,createdAt); + +@override +String toString() { + return 'AppUsageTimeEntity(id: $id, uid: $uid, deviceIdentificator: $deviceIdentificator, name: $name, startAt: $startAt, duration: $duration, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class $AppUsageTimeEntityCopyWith<$Res> { + factory $AppUsageTimeEntityCopyWith(AppUsageTimeEntity value, $Res Function(AppUsageTimeEntity) _then) = _$AppUsageTimeEntityCopyWithImpl; +@useResult +$Res call({ + String id, String uid, String deviceIdentificator, String name, String startAt, int duration, int createdAt +}); + + + + +} +/// @nodoc +class _$AppUsageTimeEntityCopyWithImpl<$Res> + implements $AppUsageTimeEntityCopyWith<$Res> { + _$AppUsageTimeEntityCopyWithImpl(this._self, this._then); + + final AppUsageTimeEntity _self; + final $Res Function(AppUsageTimeEntity) _then; + +/// Create a copy of AppUsageTimeEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? uid = null,Object? deviceIdentificator = null,Object? name = null,Object? startAt = null,Object? duration = null,Object? createdAt = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,uid: null == uid ? _self.uid : uid // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,startAt: null == startAt ? _self.startAt : startAt // ignore: cast_nullable_to_non_nullable +as String,duration: null == duration ? _self.duration : duration // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [AppUsageTimeEntity]. +extension AppUsageTimeEntityPatterns on AppUsageTimeEntity { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AppUsageTimeEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AppUsageTimeEntity() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AppUsageTimeEntity value) $default,){ +final _that = this; +switch (_that) { +case _AppUsageTimeEntity(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AppUsageTimeEntity value)? $default,){ +final _that = this; +switch (_that) { +case _AppUsageTimeEntity() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String uid, String deviceIdentificator, String name, String startAt, int duration, int createdAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AppUsageTimeEntity() when $default != null: +return $default(_that.id,_that.uid,_that.deviceIdentificator,_that.name,_that.startAt,_that.duration,_that.createdAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String uid, String deviceIdentificator, String name, String startAt, int duration, int createdAt) $default,) {final _that = this; +switch (_that) { +case _AppUsageTimeEntity(): +return $default(_that.id,_that.uid,_that.deviceIdentificator,_that.name,_that.startAt,_that.duration,_that.createdAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String uid, String deviceIdentificator, String name, String startAt, int duration, int createdAt)? $default,) {final _that = this; +switch (_that) { +case _AppUsageTimeEntity() when $default != null: +return $default(_that.id,_that.uid,_that.deviceIdentificator,_that.name,_that.startAt,_that.duration,_that.createdAt);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _AppUsageTimeEntity implements AppUsageTimeEntity { + const _AppUsageTimeEntity({required this.id, required this.uid, required this.deviceIdentificator, required this.name, required this.startAt, required this.duration, required this.createdAt}); + + +@override final String id; +@override final String uid; +@override final String deviceIdentificator; +@override final String name; +@override final String startAt; +@override final int duration; +@override final int createdAt; + +/// Create a copy of AppUsageTimeEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AppUsageTimeEntityCopyWith<_AppUsageTimeEntity> get copyWith => __$AppUsageTimeEntityCopyWithImpl<_AppUsageTimeEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppUsageTimeEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.uid, uid) || other.uid == uid)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.name, name) || other.name == name)&&(identical(other.startAt, startAt) || other.startAt == startAt)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,uid,deviceIdentificator,name,startAt,duration,createdAt); + +@override +String toString() { + return 'AppUsageTimeEntity(id: $id, uid: $uid, deviceIdentificator: $deviceIdentificator, name: $name, startAt: $startAt, duration: $duration, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$AppUsageTimeEntityCopyWith<$Res> implements $AppUsageTimeEntityCopyWith<$Res> { + factory _$AppUsageTimeEntityCopyWith(_AppUsageTimeEntity value, $Res Function(_AppUsageTimeEntity) _then) = __$AppUsageTimeEntityCopyWithImpl; +@override @useResult +$Res call({ + String id, String uid, String deviceIdentificator, String name, String startAt, int duration, int createdAt +}); + + + + +} +/// @nodoc +class __$AppUsageTimeEntityCopyWithImpl<$Res> + implements _$AppUsageTimeEntityCopyWith<$Res> { + __$AppUsageTimeEntityCopyWithImpl(this._self, this._then); + + final _AppUsageTimeEntity _self; + final $Res Function(_AppUsageTimeEntity) _then; + +/// Create a copy of AppUsageTimeEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? uid = null,Object? deviceIdentificator = null,Object? name = null,Object? startAt = null,Object? duration = null,Object? createdAt = null,}) { + return _then(_AppUsageTimeEntity( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,uid: null == uid ? _self.uid : uid // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,startAt: null == startAt ? _self.startAt : startAt // ignore: cast_nullable_to_non_nullable +as String,duration: null == duration ? _self.duration : duration // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/core/domain/entities/steps_entity.dart b/modules/legacy/modules/device_management/lib/src/core/domain/entities/steps_entity.dart new file mode 100644 index 00000000..ae718421 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/domain/entities/steps_entity.dart @@ -0,0 +1,14 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'steps_entity.freezed.dart'; + +@freezed +abstract class StepsEntity with _$StepsEntity { + const factory StepsEntity({ + required String id, + required String deviceIdentificator, + required int steps, + required int occurredAt, + required int createdAt, + }) = _StepsEntity; +} diff --git a/modules/legacy/modules/device_management/lib/src/core/domain/entities/steps_entity.freezed.dart b/modules/legacy/modules/device_management/lib/src/core/domain/entities/steps_entity.freezed.dart new file mode 100644 index 00000000..63d99bc0 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/domain/entities/steps_entity.freezed.dart @@ -0,0 +1,283 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'steps_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$StepsEntity { + + String get id; String get deviceIdentificator; int get steps; int get occurredAt; int get createdAt; +/// Create a copy of StepsEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$StepsEntityCopyWith get copyWith => _$StepsEntityCopyWithImpl(this as StepsEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is StepsEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.steps, steps) || other.steps == steps)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,steps,occurredAt,createdAt); + +@override +String toString() { + return 'StepsEntity(id: $id, deviceIdentificator: $deviceIdentificator, steps: $steps, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class $StepsEntityCopyWith<$Res> { + factory $StepsEntityCopyWith(StepsEntity value, $Res Function(StepsEntity) _then) = _$StepsEntityCopyWithImpl; +@useResult +$Res call({ + String id, String deviceIdentificator, int steps, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class _$StepsEntityCopyWithImpl<$Res> + implements $StepsEntityCopyWith<$Res> { + _$StepsEntityCopyWithImpl(this._self, this._then); + + final StepsEntity _self; + final $Res Function(StepsEntity) _then; + +/// Create a copy of StepsEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceIdentificator = null,Object? steps = null,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,steps: null == steps ? _self.steps : steps // ignore: cast_nullable_to_non_nullable +as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [StepsEntity]. +extension StepsEntityPatterns on StepsEntity { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _StepsEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _StepsEntity() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _StepsEntity value) $default,){ +final _that = this; +switch (_that) { +case _StepsEntity(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _StepsEntity value)? $default,){ +final _that = this; +switch (_that) { +case _StepsEntity() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceIdentificator, int steps, int occurredAt, int createdAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _StepsEntity() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.steps,_that.occurredAt,_that.createdAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceIdentificator, int steps, int occurredAt, int createdAt) $default,) {final _that = this; +switch (_that) { +case _StepsEntity(): +return $default(_that.id,_that.deviceIdentificator,_that.steps,_that.occurredAt,_that.createdAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceIdentificator, int steps, int occurredAt, int createdAt)? $default,) {final _that = this; +switch (_that) { +case _StepsEntity() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.steps,_that.occurredAt,_that.createdAt);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _StepsEntity implements StepsEntity { + const _StepsEntity({required this.id, required this.deviceIdentificator, required this.steps, required this.occurredAt, required this.createdAt}); + + +@override final String id; +@override final String deviceIdentificator; +@override final int steps; +@override final int occurredAt; +@override final int createdAt; + +/// Create a copy of StepsEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$StepsEntityCopyWith<_StepsEntity> get copyWith => __$StepsEntityCopyWithImpl<_StepsEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _StepsEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.steps, steps) || other.steps == steps)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,steps,occurredAt,createdAt); + +@override +String toString() { + return 'StepsEntity(id: $id, deviceIdentificator: $deviceIdentificator, steps: $steps, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$StepsEntityCopyWith<$Res> implements $StepsEntityCopyWith<$Res> { + factory _$StepsEntityCopyWith(_StepsEntity value, $Res Function(_StepsEntity) _then) = __$StepsEntityCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceIdentificator, int steps, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class __$StepsEntityCopyWithImpl<$Res> + implements _$StepsEntityCopyWith<$Res> { + __$StepsEntityCopyWithImpl(this._self, this._then); + + final _StepsEntity _self; + final $Res Function(_StepsEntity) _then; + +/// Create a copy of StepsEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceIdentificator = null,Object? steps = null,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_StepsEntity( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,steps: null == steps ? _self.steps : steps // ignore: cast_nullable_to_non_nullable +as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/core/domain/repositories/app_usage_times_repository.dart b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/app_usage_times_repository.dart new file mode 100644 index 00000000..fe9b151c --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/app_usage_times_repository.dart @@ -0,0 +1,8 @@ +import '../entities/app_usage_time_entity.dart'; + +abstract class AppUsageTimesRepository { + Future> getAppUsageTimes({ + required String identificator, + Map queryParameters = const {}, + }); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/domain/repositories/contacts_repository.dart b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/contacts_repository.dart index a6117ca9..271fdac5 100644 --- a/modules/legacy/modules/device_management/lib/src/core/domain/repositories/contacts_repository.dart +++ b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/contacts_repository.dart @@ -1,14 +1,19 @@ -import 'package:device_management/src/core/data/models/create_contact_request_model.dart'; - -import '../../../features/contacts/domain/entities/contact_entity.dart'; +import '../../data/models/create_contact_request_model.dart'; import '../../data/models/update_contact_request_model.dart'; +import '../../../features/contacts/domain/entities/contact_entity.dart'; abstract class ContactsRepository { Future> getContacts({required String userId}); - Future updateContact({required String userId, required UpdateContactRequestModel request}); + Future updateContact({required UpdateContactRequestModel request}); - Future createContact({required ContactRequestModel request}); + Future createContact({required CreateContactRequestModel request}); Future deleteContact({required String contactId}); + + Future syncContactsToDevice({ + required String userId, + required String deviceId, + required List contacts, + }); } diff --git a/modules/legacy/modules/device_management/lib/src/core/domain/repositories/health_repository.dart b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/health_repository.dart new file mode 100644 index 00000000..0cb862e9 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/health_repository.dart @@ -0,0 +1,14 @@ +import '../../../features/health/domain/entities/heartbeat_entity.dart'; +import '../../../features/health/domain/entities/oxygen_entity.dart'; + +abstract class HealthRepository { + Future> getHeartbeats({ + required String identificator, + Map queryParameters = const {}, + }); + + Future> getOxygens({ + required String identificator, + Map queryParameters = const {}, + }); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/domain/repositories/scheduled_activities_repository.dart b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/scheduled_activities_repository.dart new file mode 100644 index 00000000..71fadc06 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/scheduled_activities_repository.dart @@ -0,0 +1,20 @@ +import '../../../features/scheduled_activities/domain/entities/scheduled_activity_entity.dart'; +import '../../data/models/create_scheduled_activity_request_model.dart'; +import '../../data/models/update_scheduled_activity_request_model.dart'; + +abstract class ScheduledActivitiesRepository { + Future> getActivities({ + required String deviceId, + }); + + Future createActivity({ + required CreateScheduledActivityRequestModel request, + }); + + Future updateActivity({ + required String activityId, + required UpdateScheduledActivityRequestModel request, + }); + + Future deleteActivity({required String activityId}); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/domain/repositories/steps_repository.dart b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/steps_repository.dart new file mode 100644 index 00000000..3d510d1b --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/domain/repositories/steps_repository.dart @@ -0,0 +1,8 @@ +import '../entities/steps_entity.dart'; + +abstract class StepsRepository { + Future> getSteps({ + required String identificator, + Map queryParameters = const {}, + }); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/presentation/format_date.dart b/modules/legacy/modules/device_management/lib/src/core/presentation/format_date.dart new file mode 100644 index 00000000..16c9ef04 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/presentation/format_date.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +String formatTime(int timestampMs) { + final date = DateTime.fromMillisecondsSinceEpoch(timestampMs); + final hour = date.hour.toString().padLeft(2, '0'); + final minute = date.minute.toString().padLeft(2, '0'); + return '$hour:$minute'; +} + +String formatDate(int timestampMs) { + final date = DateTime.fromMillisecondsSinceEpoch(timestampMs); + final day = date.day.toString().padLeft(2, '0'); + final month = date.month.toString().padLeft(2, '0'); + return '$day/$month/${date.year}'; +} + +String formatDayHeader(BuildContext context, DateTime date) { + final now = DateTime.now(); + final today = DateTime(now.year, now.month, now.day); + final day = DateTime(date.year, date.month, date.day); + + if (day == today) return context.translate(I18n.today); + if (day == today.subtract(const Duration(days: 1))) { + return context.translate(I18n.yesterday); + } + + final d = date.day.toString().padLeft(2, '0'); + final m = date.month.toString().padLeft(2, '0'); + return '$d/$m/${date.year}'; +} + +String formatTimeAgo(BuildContext context, int timestampMs) { + final now = DateTime.now(); + final date = DateTime.fromMillisecondsSinceEpoch(timestampMs); + final diff = now.difference(date); + + final String time; + if (diff.inMinutes < 1) { + time = '<1 min'; + } else if (diff.inMinutes < 60) { + time = '${diff.inMinutes} min'; + } else if (diff.inHours < 24) { + time = '${diff.inHours}h'; + } else { + time = '${diff.inDays}d'; + } + + return context.translate(I18n.timeAgo, args: {'time': time}); +} + +List<(DateTime, List)> groupByDay( + List items, + int Function(T) getTimestamp, +) { + final Map> groups = {}; + + for (final item in items) { + final date = DateTime.fromMillisecondsSinceEpoch(getTimestamp(item)); + final dayKey = DateTime(date.year, date.month, date.day); + groups.putIfAbsent(dayKey, () => []).add(item); + } + + final sorted = groups.entries.toList() + ..sort((a, b) => b.key.compareTo(a.key)); + + return sorted.map((e) => (e.key, e.value)).toList(); +} diff --git a/modules/legacy/modules/device_management/lib/src/core/presentation/time_range.dart b/modules/legacy/modules/device_management/lib/src/core/presentation/time_range.dart new file mode 100644 index 00000000..467ef384 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/presentation/time_range.dart @@ -0,0 +1 @@ +enum TimeRange { today, sevenDays, thirtyDays, custom } diff --git a/modules/legacy/modules/device_management/lib/src/core/presentation/widgets/time_range_selector.dart b/modules/legacy/modules/device_management/lib/src/core/presentation/widgets/time_range_selector.dart new file mode 100644 index 00000000..757168fb --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/presentation/widgets/time_range_selector.dart @@ -0,0 +1,106 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../time_range.dart'; + +class TimeRangeSelector extends StatelessWidget { + final TimeRange selected; + final ValueChanged onSelected; + final VoidCallback onCustomTap; + final ThemePort theme; + + const TimeRangeSelector({ + super.key, + required this.selected, + required this.onSelected, + required this.onCustomTap, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + final chips = [ + (TimeRange.today, context.translate(I18n.today)), + (TimeRange.sevenDays, context.translate(I18n.sevenDays)), + (TimeRange.thirtyDays, context.translate(I18n.thirtyDays)), + (TimeRange.custom, context.translate(I18n.custom)), + ]; + + return Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + vertical: SizeUtils.getByScreen(small: 8, big: 6), + ), + child: Row( + children: chips + .map((chip) { + final (range, label) = chip; + final isCustom = range == TimeRange.custom; + return Padding( + padding: EdgeInsets.only( + right: range != chips.last.$1 + ? SizeUtils.getByScreen(small: 8, big: 6) + : 0, + ), + child: _Chip( + label: label, + isSelected: selected == range, + onTap: isCustom ? onCustomTap : () => onSelected(range), + theme: theme, + ), + ); + }) + .toList(), + ), + ); + } +} + +class _Chip extends StatelessWidget { + final String label; + final bool isSelected; + final VoidCallback onTap; + final ThemePort theme; + + const _Chip({ + required this.label, + required this.isSelected, + required this.onTap, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 14, big: 12), + vertical: SizeUtils.getByScreen(small: 8, big: 6), + ), + decoration: BoxDecoration( + color: isSelected + ? theme.getColorFor(ThemeCode.legacyPrimary) + : theme.getColorFor(ThemeCode.backgroundSecondary), + borderRadius: BorderRadius.all( + Radius.circular(SizeUtils.getByScreen(small: 20, big: 18)), + ), + ), + child: Text( + label, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + fontWeight: FontWeight.w600, + color: isSelected + ? Colors.white + : theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.6), + ), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/core/providers/app_usage_times_remote_datasource_provider.dart b/modules/legacy/modules/device_management/lib/src/core/providers/app_usage_times_remote_datasource_provider.dart new file mode 100644 index 00000000..8409daf6 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/providers/app_usage_times_remote_datasource_provider.dart @@ -0,0 +1,11 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import '../data/datasources/app_usage_times_remote_datasource.dart'; +import '../data/datasources/app_usage_times_remote_datasource_impl.dart'; + +final appUsageTimesRemoteDatasourceProvider = + Provider((ref) { + final questiaRepository = getIt(); + return AppUsageTimesRemoteDatasourceImpl(questiaRepository); +}); diff --git a/modules/legacy/modules/device_management/lib/src/core/providers/app_usage_times_repository_provider.dart b/modules/legacy/modules/device_management/lib/src/core/providers/app_usage_times_repository_provider.dart new file mode 100644 index 00000000..d0ba5fef --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/providers/app_usage_times_repository_provider.dart @@ -0,0 +1,11 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../data/repositories/app_usage_times_repository_impl.dart'; +import '../domain/repositories/app_usage_times_repository.dart'; +import 'app_usage_times_remote_datasource_provider.dart'; + +final appUsageTimesRepositoryProvider = + Provider((ref) { + final remote = ref.read(appUsageTimesRemoteDatasourceProvider); + return AppUsageTimesRepositoryImpl(remote); +}); diff --git a/modules/legacy/modules/device_management/lib/src/core/providers/health_remote_datasource_provider.dart b/modules/legacy/modules/device_management/lib/src/core/providers/health_remote_datasource_provider.dart new file mode 100644 index 00000000..a0b0da08 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/providers/health_remote_datasource_provider.dart @@ -0,0 +1,11 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import '../data/datasources/health_remote_datasource.dart'; +import '../data/datasources/health_remote_datasource_impl.dart'; + +final healthRemoteDatasourceProvider = + Provider((ref) { + final questiaRepository = getIt(); + return HealthRemoteDatasourceImpl(questiaRepository); +}); diff --git a/modules/legacy/modules/device_management/lib/src/core/providers/health_repository_provider.dart b/modules/legacy/modules/device_management/lib/src/core/providers/health_repository_provider.dart new file mode 100644 index 00000000..f8f088fe --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/providers/health_repository_provider.dart @@ -0,0 +1,10 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../data/repositories/health_repository_impl.dart'; +import '../domain/repositories/health_repository.dart'; +import 'health_remote_datasource_provider.dart'; + +final healthRepositoryProvider = Provider((ref) { + final remote = ref.read(healthRemoteDatasourceProvider); + return HealthRepositoryImpl(remote); +}); diff --git a/modules/legacy/modules/device_management/lib/src/core/providers/scheduled_activities_remote_datasource_provider.dart b/modules/legacy/modules/device_management/lib/src/core/providers/scheduled_activities_remote_datasource_provider.dart new file mode 100644 index 00000000..7e5d1074 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/providers/scheduled_activities_remote_datasource_provider.dart @@ -0,0 +1,11 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import '../data/datasources/scheduled_activities_remote_datasource.dart'; +import '../data/datasources/scheduled_activities_remote_datasource_impl.dart'; + +final scheduledActivitiesRemoteDatasourceProvider = + Provider((ref) { + final questiaRepository = getIt(); + return ScheduledActivitiesRemoteDatasourceImpl(questiaRepository); +}); diff --git a/modules/legacy/modules/device_management/lib/src/core/providers/scheduled_activities_repository_provider.dart b/modules/legacy/modules/device_management/lib/src/core/providers/scheduled_activities_repository_provider.dart new file mode 100644 index 00000000..d23a09fe --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/providers/scheduled_activities_repository_provider.dart @@ -0,0 +1,11 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../data/repositories/scheduled_activities_repository_impl.dart'; +import '../domain/repositories/scheduled_activities_repository.dart'; +import 'scheduled_activities_remote_datasource_provider.dart'; + +final scheduledActivitiesRepositoryProvider = + Provider((ref) { + final remote = ref.read(scheduledActivitiesRemoteDatasourceProvider); + return ScheduledActivitiesRepositoryImpl(remote); +}); diff --git a/modules/legacy/modules/device_management/lib/src/core/providers/steps_remote_datasource_provider.dart b/modules/legacy/modules/device_management/lib/src/core/providers/steps_remote_datasource_provider.dart new file mode 100644 index 00000000..b04ce937 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/providers/steps_remote_datasource_provider.dart @@ -0,0 +1,11 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import '../data/datasources/steps_remote_datasource.dart'; +import '../data/datasources/steps_remote_datasource_impl.dart'; + +final stepsRemoteDatasourceProvider = + Provider((ref) { + final questiaRepository = getIt(); + return StepsRemoteDatasourceImpl(questiaRepository); +}); diff --git a/modules/legacy/modules/device_management/lib/src/core/providers/steps_repository_provider.dart b/modules/legacy/modules/device_management/lib/src/core/providers/steps_repository_provider.dart new file mode 100644 index 00000000..6f1bc450 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/core/providers/steps_repository_provider.dart @@ -0,0 +1,10 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../data/repositories/steps_repository_impl.dart'; +import '../domain/repositories/steps_repository.dart'; +import 'steps_remote_datasource_provider.dart'; + +final stepsRepositoryProvider = Provider((ref) { + final remote = ref.read(stepsRemoteDatasourceProvider); + return StepsRepositoryImpl(remote); +}); diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/activity_meter_builder.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/activity_meter_builder.dart new file mode 100644 index 00000000..575f777b --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/activity_meter_builder.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import 'presentation/activity_meter_screen.dart'; + +class ActivityMeterBuilder { + const ActivityMeterBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + return MaterialPage( + key: state.pageKey, + child: const ActivityMeterScreen(), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/activity_meter_screen.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/activity_meter_screen.dart new file mode 100644 index 00000000..813ada40 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/activity_meter_screen.dart @@ -0,0 +1,128 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../../core/presentation/widgets/time_range_selector.dart'; +import 'state/activity_meter_view_model.dart'; +import 'widgets/steps_bar_chart.dart'; +import 'widgets/steps_history_section.dart'; +import 'widgets/steps_progress_ring.dart'; +import 'widgets/steps_stats_row.dart'; + +class ActivityMeterScreen extends ConsumerWidget { + const ActivityMeterScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final state = ref.watch(activityMeterViewModelProvider); + final vm = ref.read(activityMeterViewModelProvider.notifier); + + ref.listen( + activityMeterViewModelProvider.select((s) => s.errorMessage), + (previous, next) { + if (next.isNotEmpty) { + showTopSnackbar(context, message: next, type: MessageType.error); + } + }, + ); + + final hasData = state.todayTotal > 0 || + state.chartData.isNotEmpty || + state.historyData.isNotEmpty; + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.activityMeter), + body: state.isLoading + ? const Center(child: CircularProgressIndicator()) + : SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (!hasData) + Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + vertical: SizeUtils.getByScreen(small: 12, big: 10), + ), + child: Row( + children: [ + Icon( + Icons.info_outline, + color: theme.getColorFor(ThemeCode.legacyPrimary), + size: SizeUtils.getByScreen(small: 20, big: 22), + ), + SizedBox(width: SizeUtils.getByScreen(small: 8, big: 10)), + Expanded( + child: Text( + context.translate(I18n.noActivityData), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 15), + color: theme.getColorFor(ThemeCode.textPrimary).withAlpha(178), + ), + ), + ), + ], + ), + ), + StepsProgressRing( + steps: state.todayTotal, + goal: state.dailyGoal, + theme: theme, + ), + TimeRangeSelector( + selected: state.timeRange, + onSelected: (range) => vm.selectTimeRange(range), + onCustomTap: () => _pickCustomRange(context, vm), + theme: theme, + ), + StepsBarChart( + data: state.chartData, + theme: theme, + ), + SizedBox( + height: SizeUtils.getByScreen(small: 8, big: 6), + ), + StepsStatsRow( + stats: state.stats, + theme: theme, + ), + SizedBox( + height: SizeUtils.getByScreen(small: 16, big: 14), + ), + StepsHistorySection( + items: state.historyData, + dailyGoal: state.dailyGoal, + hasMore: state.hasMoreHistory, + isLoadingMore: state.isLoadingMore, + onLoadMore: () => vm.loadMoreHistory(), + theme: theme, + ), + SizedBox( + height: SizeUtils.getByScreen(small: 24, big: 20), + ), + ], + ), + ), + ); + } + + Future _pickCustomRange( + BuildContext context, + ActivityMeterViewModel vm, + ) async { + final now = DateTime.now(); + final picked = await showDateRangePicker( + context: context, + firstDate: now.subtract(const Duration(days: 365)), + lastDate: now, + ); + if (picked != null) { + vm.selectCustomRange(picked.start, picked.end); + } + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/format_steps.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/format_steps.dart new file mode 100644 index 00000000..6ff61ab6 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/format_steps.dart @@ -0,0 +1,9 @@ +String formatStepsNumber(int n) { + if (n >= 1000) { + final thousands = n ~/ 1000; + final remainder = (n % 1000) ~/ 100; + if (remainder == 0) return '${thousands}k'; + return '$thousands.${remainder}k'; + } + return n.toString(); +} diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_model.dart new file mode 100644 index 00000000..87c2bba2 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_model.dart @@ -0,0 +1,250 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; + +import '../../../../core/data/datasources/health_query_builder.dart'; +import '../../../../core/presentation/time_range.dart'; +import '../../../../core/domain/repositories/steps_repository.dart'; +import '../../../../core/providers/steps_repository_provider.dart'; +import '../../../../core/domain/entities/steps_entity.dart'; +import 'activity_meter_view_state.dart'; + +final activityMeterViewModelProvider = NotifierProvider.autoDispose< + ActivityMeterViewModel, ActivityMeterViewState>( + ActivityMeterViewModel.new, +); + +class ActivityMeterViewModel extends Notifier { + late final StepsRepository _repository; + + static const int _historyPageSize = 20; + + @override + ActivityMeterViewState build() { + _repository = ref.read(stepsRepositoryProvider); + _init(); + return const ActivityMeterViewState(); + } + + String? get _identificator => + ref.read(selectedDeviceProvider)?.identificator; + + Future selectTimeRange(TimeRange range) async { + if (range == state.timeRange) return; + state = state.copyWith(timeRange: range, isLoading: true); + await _loadFilteredData(); + } + + Future selectCustomRange(DateTime start, DateTime end) async { + state = state.copyWith( + timeRange: TimeRange.custom, + customStart: start, + customEnd: end, + isLoading: true, + ); + await _loadFilteredData(); + } + + Future loadMoreHistory() async { + if (state.isLoadingMore || !state.hasMoreHistory) return; + final identificator = _identificator; + if (identificator == null) return; + + state = state.copyWith(isLoadingMore: true); + + try { + final nextPage = state.currentHistoryPage + 1; + final filters = _buildTimeFilters(); + + final steps = await _repository.getSteps( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + page: nextPage, + pageSize: _historyPageSize, + filters: filters, + ), + ); + if (!ref.mounted) return; + + final newDaily = _groupByDay(steps); + final merged = _mergeHistory(state.historyData, newDaily); + + state = state.copyWith( + historyData: merged, + currentHistoryPage: nextPage, + hasMoreHistory: steps.length >= _historyPageSize, + isLoadingMore: false, + ); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith( + isLoadingMore: false, + errorMessage: _formatError(e), + ); + } + } + + Future _init() async { + final identificator = _identificator; + if (identificator == null) { + state = state.copyWith(isLoading: false); + return; + } + + try { + final todayStart = DateTime.now(); + final todayFilters = HealthQueryBuilder.timeRangeFilters( + start: DateTime(todayStart.year, todayStart.month, todayStart.day), + end: todayStart, + ); + + final todaySteps = await _repository.getSteps( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + filters: todayFilters, + ), + ); + if (!ref.mounted) return; + + final todayTotal = todaySteps.fold(0, (sum, s) => sum + s.steps); + state = state.copyWith(todayTotal: todayTotal); + + await _loadFilteredData(); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } + } + + Future _loadFilteredData() async { + final identificator = _identificator; + if (identificator == null) { + state = state.copyWith(isLoading: false); + return; + } + + try { + final filters = _buildTimeFilters(); + + final (chartSteps, histSteps) = await ( + _repository.getSteps( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.asc, + filters: filters, + ), + ), + _repository.getSteps( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + page: 1, + pageSize: _historyPageSize, + filters: filters, + ), + ), + ).wait; + if (!ref.mounted) return; + + final chartDaily = _groupByDay(chartSteps); + final historyDaily = _groupByDay(histSteps).reversed.toList(); + + state = state.copyWith( + chartData: chartDaily, + historyData: historyDaily, + currentHistoryPage: 1, + hasMoreHistory: histSteps.length >= _historyPageSize, + stats: _computeStats(chartDaily), + isLoading: false, + errorMessage: '', + ); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } + } + + List _groupByDay(List steps) { + final Map groups = {}; + + for (final step in steps) { + final date = DateTime.fromMillisecondsSinceEpoch(step.occurredAt); + final dayKey = DateTime(date.year, date.month, date.day); + groups[dayKey] = (groups[dayKey] ?? 0) + step.steps; + } + + final sorted = groups.entries.toList() + ..sort((a, b) => a.key.compareTo(b.key)); + + return sorted + .map((e) => DailySteps(date: e.key, totalSteps: e.value)) + .toList(); + } + + List _mergeHistory( + List existing, + List newItems, + ) { + final Map merged = { + for (final d in existing) d.date: d.totalSteps, + }; + for (final d in newItems) { + merged[d.date] = (merged[d.date] ?? 0) + d.totalSteps; + } + + final sorted = merged.entries.toList() + ..sort((a, b) => b.key.compareTo(a.key)); + + return sorted + .map((e) => DailySteps(date: e.key, totalSteps: e.value)) + .toList(); + } + + StepsStats _computeStats(List daily) { + if (daily.isEmpty) return const StepsStats(); + + final total = daily.fold(0, (sum, d) => sum + d.totalSteps); + final best = daily.reduce( + (a, b) => a.totalSteps >= b.totalSteps ? a : b, + ); + + return StepsStats( + avgPerDay: (total / daily.length).round(), + total: total, + bestDaySteps: best.totalSteps, + ); + } + + List? _buildTimeFilters() { + final range = _getTimeRange(); + if (range == null) return null; + + final (start, end) = range; + return HealthQueryBuilder.timeRangeFilters(start: start, end: end); + } + + (DateTime, DateTime)? _getTimeRange() { + final now = DateTime.now(); + final todayStart = DateTime(now.year, now.month, now.day); + + switch (state.timeRange) { + case TimeRange.today: + return (todayStart, now); + case TimeRange.sevenDays: + return (todayStart.subtract(const Duration(days: 6)), now); + case TimeRange.thirtyDays: + return (todayStart.subtract(const Duration(days: 29)), now); + case TimeRange.custom: + if (state.customStart != null && state.customEnd != null) { + return (state.customStart!, state.customEnd!); + } + return null; + } + } + + String _formatError(Object e) { + final msg = e.toString(); + return msg.startsWith('Exception: ') ? msg.substring(11) : msg; + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.dart new file mode 100644 index 00000000..86f5ad60 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.dart @@ -0,0 +1,41 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../../../core/presentation/time_range.dart'; + +part 'activity_meter_view_state.freezed.dart'; + +@freezed +abstract class DailySteps with _$DailySteps { + const factory DailySteps({ + required DateTime date, + required int totalSteps, + }) = _DailySteps; +} + +@freezed +abstract class StepsStats with _$StepsStats { + const factory StepsStats({ + @Default(0) int avgPerDay, + @Default(0) int total, + @Default(0) int bestDaySteps, + }) = _StepsStats; +} + +@freezed +abstract class ActivityMeterViewState with _$ActivityMeterViewState { + const factory ActivityMeterViewState({ + @Default(0) int todayTotal, + @Default(8000) int dailyGoal, + @Default([]) List chartData, + @Default([]) List historyData, + @Default(1) int currentHistoryPage, + @Default(false) bool hasMoreHistory, + @Default(StepsStats()) StepsStats stats, + @Default(TimeRange.today) TimeRange timeRange, + DateTime? customStart, + DateTime? customEnd, + @Default(true) bool isLoading, + @Default(false) bool isLoadingMore, + @Default('') String errorMessage, + }) = _ActivityMeterViewState; +} diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.freezed.dart new file mode 100644 index 00000000..53c2392d --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.freezed.dart @@ -0,0 +1,860 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'activity_meter_view_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$DailySteps { + + DateTime get date; int get totalSteps; +/// Create a copy of DailySteps +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$DailyStepsCopyWith get copyWith => _$DailyStepsCopyWithImpl(this as DailySteps, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is DailySteps&&(identical(other.date, date) || other.date == date)&&(identical(other.totalSteps, totalSteps) || other.totalSteps == totalSteps)); +} + + +@override +int get hashCode => Object.hash(runtimeType,date,totalSteps); + +@override +String toString() { + return 'DailySteps(date: $date, totalSteps: $totalSteps)'; +} + + +} + +/// @nodoc +abstract mixin class $DailyStepsCopyWith<$Res> { + factory $DailyStepsCopyWith(DailySteps value, $Res Function(DailySteps) _then) = _$DailyStepsCopyWithImpl; +@useResult +$Res call({ + DateTime date, int totalSteps +}); + + + + +} +/// @nodoc +class _$DailyStepsCopyWithImpl<$Res> + implements $DailyStepsCopyWith<$Res> { + _$DailyStepsCopyWithImpl(this._self, this._then); + + final DailySteps _self; + final $Res Function(DailySteps) _then; + +/// Create a copy of DailySteps +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? date = null,Object? totalSteps = null,}) { + return _then(_self.copyWith( +date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable +as DateTime,totalSteps: null == totalSteps ? _self.totalSteps : totalSteps // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [DailySteps]. +extension DailyStepsPatterns on DailySteps { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _DailySteps value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _DailySteps() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _DailySteps value) $default,){ +final _that = this; +switch (_that) { +case _DailySteps(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _DailySteps value)? $default,){ +final _that = this; +switch (_that) { +case _DailySteps() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( DateTime date, int totalSteps)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _DailySteps() when $default != null: +return $default(_that.date,_that.totalSteps);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( DateTime date, int totalSteps) $default,) {final _that = this; +switch (_that) { +case _DailySteps(): +return $default(_that.date,_that.totalSteps);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( DateTime date, int totalSteps)? $default,) {final _that = this; +switch (_that) { +case _DailySteps() when $default != null: +return $default(_that.date,_that.totalSteps);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _DailySteps implements DailySteps { + const _DailySteps({required this.date, required this.totalSteps}); + + +@override final DateTime date; +@override final int totalSteps; + +/// Create a copy of DailySteps +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$DailyStepsCopyWith<_DailySteps> get copyWith => __$DailyStepsCopyWithImpl<_DailySteps>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _DailySteps&&(identical(other.date, date) || other.date == date)&&(identical(other.totalSteps, totalSteps) || other.totalSteps == totalSteps)); +} + + +@override +int get hashCode => Object.hash(runtimeType,date,totalSteps); + +@override +String toString() { + return 'DailySteps(date: $date, totalSteps: $totalSteps)'; +} + + +} + +/// @nodoc +abstract mixin class _$DailyStepsCopyWith<$Res> implements $DailyStepsCopyWith<$Res> { + factory _$DailyStepsCopyWith(_DailySteps value, $Res Function(_DailySteps) _then) = __$DailyStepsCopyWithImpl; +@override @useResult +$Res call({ + DateTime date, int totalSteps +}); + + + + +} +/// @nodoc +class __$DailyStepsCopyWithImpl<$Res> + implements _$DailyStepsCopyWith<$Res> { + __$DailyStepsCopyWithImpl(this._self, this._then); + + final _DailySteps _self; + final $Res Function(_DailySteps) _then; + +/// Create a copy of DailySteps +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? date = null,Object? totalSteps = null,}) { + return _then(_DailySteps( +date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable +as DateTime,totalSteps: null == totalSteps ? _self.totalSteps : totalSteps // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +/// @nodoc +mixin _$StepsStats { + + int get avgPerDay; int get total; int get bestDaySteps; +/// Create a copy of StepsStats +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$StepsStatsCopyWith get copyWith => _$StepsStatsCopyWithImpl(this as StepsStats, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is StepsStats&&(identical(other.avgPerDay, avgPerDay) || other.avgPerDay == avgPerDay)&&(identical(other.total, total) || other.total == total)&&(identical(other.bestDaySteps, bestDaySteps) || other.bestDaySteps == bestDaySteps)); +} + + +@override +int get hashCode => Object.hash(runtimeType,avgPerDay,total,bestDaySteps); + +@override +String toString() { + return 'StepsStats(avgPerDay: $avgPerDay, total: $total, bestDaySteps: $bestDaySteps)'; +} + + +} + +/// @nodoc +abstract mixin class $StepsStatsCopyWith<$Res> { + factory $StepsStatsCopyWith(StepsStats value, $Res Function(StepsStats) _then) = _$StepsStatsCopyWithImpl; +@useResult +$Res call({ + int avgPerDay, int total, int bestDaySteps +}); + + + + +} +/// @nodoc +class _$StepsStatsCopyWithImpl<$Res> + implements $StepsStatsCopyWith<$Res> { + _$StepsStatsCopyWithImpl(this._self, this._then); + + final StepsStats _self; + final $Res Function(StepsStats) _then; + +/// Create a copy of StepsStats +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? avgPerDay = null,Object? total = null,Object? bestDaySteps = null,}) { + return _then(_self.copyWith( +avgPerDay: null == avgPerDay ? _self.avgPerDay : avgPerDay // ignore: cast_nullable_to_non_nullable +as int,total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,bestDaySteps: null == bestDaySteps ? _self.bestDaySteps : bestDaySteps // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [StepsStats]. +extension StepsStatsPatterns on StepsStats { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _StepsStats value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _StepsStats() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _StepsStats value) $default,){ +final _that = this; +switch (_that) { +case _StepsStats(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _StepsStats value)? $default,){ +final _that = this; +switch (_that) { +case _StepsStats() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int avgPerDay, int total, int bestDaySteps)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _StepsStats() when $default != null: +return $default(_that.avgPerDay,_that.total,_that.bestDaySteps);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int avgPerDay, int total, int bestDaySteps) $default,) {final _that = this; +switch (_that) { +case _StepsStats(): +return $default(_that.avgPerDay,_that.total,_that.bestDaySteps);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int avgPerDay, int total, int bestDaySteps)? $default,) {final _that = this; +switch (_that) { +case _StepsStats() when $default != null: +return $default(_that.avgPerDay,_that.total,_that.bestDaySteps);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _StepsStats implements StepsStats { + const _StepsStats({this.avgPerDay = 0, this.total = 0, this.bestDaySteps = 0}); + + +@override@JsonKey() final int avgPerDay; +@override@JsonKey() final int total; +@override@JsonKey() final int bestDaySteps; + +/// Create a copy of StepsStats +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$StepsStatsCopyWith<_StepsStats> get copyWith => __$StepsStatsCopyWithImpl<_StepsStats>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _StepsStats&&(identical(other.avgPerDay, avgPerDay) || other.avgPerDay == avgPerDay)&&(identical(other.total, total) || other.total == total)&&(identical(other.bestDaySteps, bestDaySteps) || other.bestDaySteps == bestDaySteps)); +} + + +@override +int get hashCode => Object.hash(runtimeType,avgPerDay,total,bestDaySteps); + +@override +String toString() { + return 'StepsStats(avgPerDay: $avgPerDay, total: $total, bestDaySteps: $bestDaySteps)'; +} + + +} + +/// @nodoc +abstract mixin class _$StepsStatsCopyWith<$Res> implements $StepsStatsCopyWith<$Res> { + factory _$StepsStatsCopyWith(_StepsStats value, $Res Function(_StepsStats) _then) = __$StepsStatsCopyWithImpl; +@override @useResult +$Res call({ + int avgPerDay, int total, int bestDaySteps +}); + + + + +} +/// @nodoc +class __$StepsStatsCopyWithImpl<$Res> + implements _$StepsStatsCopyWith<$Res> { + __$StepsStatsCopyWithImpl(this._self, this._then); + + final _StepsStats _self; + final $Res Function(_StepsStats) _then; + +/// Create a copy of StepsStats +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? avgPerDay = null,Object? total = null,Object? bestDaySteps = null,}) { + return _then(_StepsStats( +avgPerDay: null == avgPerDay ? _self.avgPerDay : avgPerDay // ignore: cast_nullable_to_non_nullable +as int,total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,bestDaySteps: null == bestDaySteps ? _self.bestDaySteps : bestDaySteps // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +/// @nodoc +mixin _$ActivityMeterViewState { + + int get todayTotal; int get dailyGoal; List get chartData; List get historyData; int get currentHistoryPage; bool get hasMoreHistory; StepsStats get stats; TimeRange get timeRange; DateTime? get customStart; DateTime? get customEnd; bool get isLoading; bool get isLoadingMore; String get errorMessage; +/// Create a copy of ActivityMeterViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ActivityMeterViewStateCopyWith get copyWith => _$ActivityMeterViewStateCopyWithImpl(this as ActivityMeterViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ActivityMeterViewState&&(identical(other.todayTotal, todayTotal) || other.todayTotal == todayTotal)&&(identical(other.dailyGoal, dailyGoal) || other.dailyGoal == dailyGoal)&&const DeepCollectionEquality().equals(other.chartData, chartData)&&const DeepCollectionEquality().equals(other.historyData, historyData)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.stats, stats) || other.stats == stats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,todayTotal,dailyGoal,const DeepCollectionEquality().hash(chartData),const DeepCollectionEquality().hash(historyData),currentHistoryPage,hasMoreHistory,stats,timeRange,customStart,customEnd,isLoading,isLoadingMore,errorMessage); + +@override +String toString() { + return 'ActivityMeterViewState(todayTotal: $todayTotal, dailyGoal: $dailyGoal, chartData: $chartData, historyData: $historyData, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, stats: $stats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class $ActivityMeterViewStateCopyWith<$Res> { + factory $ActivityMeterViewStateCopyWith(ActivityMeterViewState value, $Res Function(ActivityMeterViewState) _then) = _$ActivityMeterViewStateCopyWithImpl; +@useResult +$Res call({ + int todayTotal, int dailyGoal, List chartData, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage +}); + + +$StepsStatsCopyWith<$Res> get stats; + +} +/// @nodoc +class _$ActivityMeterViewStateCopyWithImpl<$Res> + implements $ActivityMeterViewStateCopyWith<$Res> { + _$ActivityMeterViewStateCopyWithImpl(this._self, this._then); + + final ActivityMeterViewState _self; + final $Res Function(ActivityMeterViewState) _then; + +/// Create a copy of ActivityMeterViewState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? todayTotal = null,Object? dailyGoal = null,Object? chartData = null,Object? historyData = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? stats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorMessage = null,}) { + return _then(_self.copyWith( +todayTotal: null == todayTotal ? _self.todayTotal : todayTotal // ignore: cast_nullable_to_non_nullable +as int,dailyGoal: null == dailyGoal ? _self.dailyGoal : dailyGoal // ignore: cast_nullable_to_non_nullable +as int,chartData: null == chartData ? _self.chartData : chartData // ignore: cast_nullable_to_non_nullable +as List,historyData: null == historyData ? _self.historyData : historyData // ignore: cast_nullable_to_non_nullable +as List,currentHistoryPage: null == currentHistoryPage ? _self.currentHistoryPage : currentHistoryPage // ignore: cast_nullable_to_non_nullable +as int,hasMoreHistory: null == hasMoreHistory ? _self.hasMoreHistory : hasMoreHistory // ignore: cast_nullable_to_non_nullable +as bool,stats: null == stats ? _self.stats : stats // ignore: cast_nullable_to_non_nullable +as StepsStats,timeRange: null == timeRange ? _self.timeRange : timeRange // ignore: cast_nullable_to_non_nullable +as TimeRange,customStart: freezed == customStart ? _self.customStart : customStart // ignore: cast_nullable_to_non_nullable +as DateTime?,customEnd: freezed == customEnd ? _self.customEnd : customEnd // ignore: cast_nullable_to_non_nullable +as DateTime?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} +/// Create a copy of ActivityMeterViewState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$StepsStatsCopyWith<$Res> get stats { + + return $StepsStatsCopyWith<$Res>(_self.stats, (value) { + return _then(_self.copyWith(stats: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [ActivityMeterViewState]. +extension ActivityMeterViewStatePatterns on ActivityMeterViewState { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _ActivityMeterViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _ActivityMeterViewState() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _ActivityMeterViewState value) $default,){ +final _that = this; +switch (_that) { +case _ActivityMeterViewState(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ActivityMeterViewState value)? $default,){ +final _that = this; +switch (_that) { +case _ActivityMeterViewState() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int todayTotal, int dailyGoal, List chartData, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _ActivityMeterViewState() when $default != null: +return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int todayTotal, int dailyGoal, List chartData, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage) $default,) {final _that = this; +switch (_that) { +case _ActivityMeterViewState(): +return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int todayTotal, int dailyGoal, List chartData, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage)? $default,) {final _that = this; +switch (_that) { +case _ActivityMeterViewState() when $default != null: +return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _ActivityMeterViewState implements ActivityMeterViewState { + const _ActivityMeterViewState({this.todayTotal = 0, this.dailyGoal = 8000, final List chartData = const [], final List historyData = const [], this.currentHistoryPage = 1, this.hasMoreHistory = false, this.stats = const StepsStats(), this.timeRange = TimeRange.today, this.customStart, this.customEnd, this.isLoading = true, this.isLoadingMore = false, this.errorMessage = ''}): _chartData = chartData,_historyData = historyData; + + +@override@JsonKey() final int todayTotal; +@override@JsonKey() final int dailyGoal; + final List _chartData; +@override@JsonKey() List get chartData { + if (_chartData is EqualUnmodifiableListView) return _chartData; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_chartData); +} + + final List _historyData; +@override@JsonKey() List get historyData { + if (_historyData is EqualUnmodifiableListView) return _historyData; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_historyData); +} + +@override@JsonKey() final int currentHistoryPage; +@override@JsonKey() final bool hasMoreHistory; +@override@JsonKey() final StepsStats stats; +@override@JsonKey() final TimeRange timeRange; +@override final DateTime? customStart; +@override final DateTime? customEnd; +@override@JsonKey() final bool isLoading; +@override@JsonKey() final bool isLoadingMore; +@override@JsonKey() final String errorMessage; + +/// Create a copy of ActivityMeterViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ActivityMeterViewStateCopyWith<_ActivityMeterViewState> get copyWith => __$ActivityMeterViewStateCopyWithImpl<_ActivityMeterViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ActivityMeterViewState&&(identical(other.todayTotal, todayTotal) || other.todayTotal == todayTotal)&&(identical(other.dailyGoal, dailyGoal) || other.dailyGoal == dailyGoal)&&const DeepCollectionEquality().equals(other._chartData, _chartData)&&const DeepCollectionEquality().equals(other._historyData, _historyData)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.stats, stats) || other.stats == stats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,todayTotal,dailyGoal,const DeepCollectionEquality().hash(_chartData),const DeepCollectionEquality().hash(_historyData),currentHistoryPage,hasMoreHistory,stats,timeRange,customStart,customEnd,isLoading,isLoadingMore,errorMessage); + +@override +String toString() { + return 'ActivityMeterViewState(todayTotal: $todayTotal, dailyGoal: $dailyGoal, chartData: $chartData, historyData: $historyData, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, stats: $stats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class _$ActivityMeterViewStateCopyWith<$Res> implements $ActivityMeterViewStateCopyWith<$Res> { + factory _$ActivityMeterViewStateCopyWith(_ActivityMeterViewState value, $Res Function(_ActivityMeterViewState) _then) = __$ActivityMeterViewStateCopyWithImpl; +@override @useResult +$Res call({ + int todayTotal, int dailyGoal, List chartData, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage +}); + + +@override $StepsStatsCopyWith<$Res> get stats; + +} +/// @nodoc +class __$ActivityMeterViewStateCopyWithImpl<$Res> + implements _$ActivityMeterViewStateCopyWith<$Res> { + __$ActivityMeterViewStateCopyWithImpl(this._self, this._then); + + final _ActivityMeterViewState _self; + final $Res Function(_ActivityMeterViewState) _then; + +/// Create a copy of ActivityMeterViewState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? todayTotal = null,Object? dailyGoal = null,Object? chartData = null,Object? historyData = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? stats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorMessage = null,}) { + return _then(_ActivityMeterViewState( +todayTotal: null == todayTotal ? _self.todayTotal : todayTotal // ignore: cast_nullable_to_non_nullable +as int,dailyGoal: null == dailyGoal ? _self.dailyGoal : dailyGoal // ignore: cast_nullable_to_non_nullable +as int,chartData: null == chartData ? _self._chartData : chartData // ignore: cast_nullable_to_non_nullable +as List,historyData: null == historyData ? _self._historyData : historyData // ignore: cast_nullable_to_non_nullable +as List,currentHistoryPage: null == currentHistoryPage ? _self.currentHistoryPage : currentHistoryPage // ignore: cast_nullable_to_non_nullable +as int,hasMoreHistory: null == hasMoreHistory ? _self.hasMoreHistory : hasMoreHistory // ignore: cast_nullable_to_non_nullable +as bool,stats: null == stats ? _self.stats : stats // ignore: cast_nullable_to_non_nullable +as StepsStats,timeRange: null == timeRange ? _self.timeRange : timeRange // ignore: cast_nullable_to_non_nullable +as TimeRange,customStart: freezed == customStart ? _self.customStart : customStart // ignore: cast_nullable_to_non_nullable +as DateTime?,customEnd: freezed == customEnd ? _self.customEnd : customEnd // ignore: cast_nullable_to_non_nullable +as DateTime?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +/// Create a copy of ActivityMeterViewState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$StepsStatsCopyWith<$Res> get stats { + + return $StepsStatsCopyWith<$Res>(_self.stats, (value) { + return _then(_self.copyWith(stats: value)); + }); +} +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_bar_chart.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_bar_chart.dart new file mode 100644 index 00000000..d82c25d1 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_bar_chart.dart @@ -0,0 +1,160 @@ +import 'package:design_system/design_system.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:utils/utils.dart'; + +import '../state/activity_meter_view_state.dart'; + +class StepsBarChart extends StatelessWidget { + final List data; + final ThemePort theme; + + const StepsBarChart({ + super.key, + required this.data, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + if (data.isEmpty) { + return SizedBox( + height: SizeUtils.getByScreen(small: 180, big: 160), + child: Center( + child: Text( + '--', + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 16, big: 14), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.3), + ), + ), + ), + ); + } + + final maxY = data + .map((d) => d.totalSteps.toDouble()) + .reduce((a, b) => a > b ? a : b); + + return Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: SizedBox( + height: SizeUtils.getByScreen(small: 180, big: 160), + child: BarChart( + BarChartData( + maxY: maxY * 1.15, + barGroups: data.asMap().entries.map((entry) { + return BarChartGroupData( + x: entry.key, + barRods: [ + BarChartRodData( + toY: entry.value.totalSteps.toDouble(), + color: theme.getColorFor(ThemeCode.legacyPrimary), + width: _barWidth, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + SizeUtils.getByScreen(small: 4, big: 3), + ), + ), + ), + ], + ); + }).toList(), + gridData: FlGridData( + show: true, + drawVerticalLine: false, + horizontalInterval: _computeInterval(maxY), + getDrawingHorizontalLine: (value) => FlLine( + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.08), + strokeWidth: 1, + ), + ), + titlesData: FlTitlesData( + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: SizeUtils.getByScreen(small: 36, big: 32), + getTitlesWidget: (value, meta) => Text( + _formatAxis(value), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 10, big: 9), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.4), + ), + ), + ), + ), + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: data.length <= 14, + getTitlesWidget: (value, meta) { + final index = value.toInt(); + if (index < 0 || index >= data.length) { + return const SizedBox.shrink(); + } + final date = data[index].date; + return Text( + '${date.day}/${date.month}', + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 9, big: 8), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.4), + ), + ); + }, + ), + ), + topTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + rightTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + ), + borderData: FlBorderData(show: false), + barTouchData: BarTouchData( + touchTooltipData: BarTouchTooltipData( + getTooltipColor: (_) => + theme.getColorFor(ThemeCode.backgroundSecondary), + getTooltipItem: (group, groupIndex, rod, rodIndex) { + return BarTooltipItem( + rod.toY.toInt().toString(), + TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11), + fontWeight: FontWeight.w600, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ); + }, + ), + ), + ), + ), + ), + ); + } + + double get _barWidth { + if (data.length <= 7) return SizeUtils.getByScreen(small: 24, big: 20); + if (data.length <= 14) return SizeUtils.getByScreen(small: 14, big: 12); + return SizeUtils.getByScreen(small: 8, big: 6); + } + + double _computeInterval(double maxY) { + if (maxY <= 0) return 1; + return (maxY / 4).ceilToDouble(); + } + + String _formatAxis(double value) { + if (value >= 1000) return '${(value / 1000).toStringAsFixed(0)}k'; + return value.toInt().toString(); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_history_section.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_history_section.dart new file mode 100644 index 00000000..fec5ad14 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_history_section.dart @@ -0,0 +1,190 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../../../core/presentation/format_date.dart'; +import '../format_steps.dart'; +import '../state/activity_meter_view_state.dart'; + +class StepsHistorySection extends StatelessWidget { + final List items; + final int dailyGoal; + final bool hasMore; + final bool isLoadingMore; + final VoidCallback onLoadMore; + final ThemePort theme; + + const StepsHistorySection({ + super.key, + required this.items, + required this.dailyGoal, + required this.hasMore, + required this.isLoadingMore, + required this.onLoadMore, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: Text( + context.translate(I18n.history), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 14), + fontWeight: FontWeight.w600, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + ), + ...items.map( + (day) => _StepsHistoryTile( + dailySteps: day, + dailyGoal: dailyGoal, + theme: theme, + ), + ), + if (hasMore) + Padding( + padding: EdgeInsets.all( + SizeUtils.getByScreen(small: 16, big: 14), + ), + child: Center( + child: isLoadingMore + ? const CircularProgressIndicator() + : TextButton( + onPressed: onLoadMore, + child: Text( + context.translate(I18n.loadMore), + style: TextStyle( + color: theme.getColorFor(ThemeCode.legacyPrimary), + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + ], + ); + } +} + +class _StepsHistoryTile extends StatelessWidget { + final DailySteps dailySteps; + final int dailyGoal; + final ThemePort theme; + + const _StepsHistoryTile({ + required this.dailySteps, + required this.dailyGoal, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + final progress = dailyGoal > 0 + ? (dailySteps.totalSteps / dailyGoal).clamp(0.0, 1.0) + : 0.0; + final percentage = (progress * 100).round(); + final goalReached = dailySteps.totalSteps >= dailyGoal; + + return Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 22, big: 21), + vertical: SizeUtils.getByScreen(small: 4, big: 3), + ), + child: Container( + padding: EdgeInsets.all( + SizeUtils.getByScreen(small: 14, big: 12), + ), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundSecondary), + borderRadius: BorderRadius.all( + Radius.circular(SizeUtils.getByScreen(small: 12, big: 10)), + ), + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + formatDayHeader(context, dailySteps.date), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.6), + ), + ), + Row( + children: [ + Text( + formatStepsNumber(dailySteps.totalSteps), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 16, big: 14), + fontWeight: FontWeight.w700, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + if (goalReached) ...[ + SizedBox( + width: SizeUtils.getByScreen(small: 4, big: 3), + ), + Icon( + Icons.star_rounded, + size: SizeUtils.getByScreen(small: 16, big: 14), + color: const Color(0xFFFF9800), + ), + ], + ], + ), + ], + ), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 6)), + Row( + children: [ + Expanded( + child: ClipRRect( + borderRadius: BorderRadius.all( + Radius.circular( + SizeUtils.getByScreen(small: 4, big: 3), + ), + ), + child: LinearProgressIndicator( + value: progress, + minHeight: SizeUtils.getByScreen(small: 6, big: 5), + backgroundColor: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.1), + valueColor: AlwaysStoppedAnimation( + theme.getColorFor(ThemeCode.legacyPrimary), + ), + ), + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 8, big: 6)), + Text( + '$percentage%', + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11), + fontWeight: FontWeight.w600, + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_progress_ring.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_progress_ring.dart new file mode 100644 index 00000000..99c90994 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_progress_ring.dart @@ -0,0 +1,138 @@ +import 'dart:math'; + +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../format_steps.dart'; + +class StepsProgressRing extends StatelessWidget { + final int steps; + final int goal; + final ThemePort theme; + + const StepsProgressRing({ + super.key, + required this.steps, + required this.goal, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + final progress = goal > 0 ? (steps / goal).clamp(0.0, 1.0) : 0.0; + final percentage = (progress * 100).round(); + final ringSize = SizeUtils.getByScreen(small: 160.0, big: 140.0); + + return Padding( + padding: EdgeInsets.symmetric( + vertical: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: Column( + children: [ + SizedBox( + width: ringSize, + height: ringSize, + child: CustomPaint( + painter: _RingPainter( + progress: progress, + activeColor: theme.getColorFor(ThemeCode.legacyPrimary), + trackColor: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.1), + ), + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.directions_walk_rounded, + size: SizeUtils.getByScreen(small: 28, big: 24), + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), + Text( + formatStepsNumber(steps), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 28, big: 24), + fontWeight: FontWeight.w700, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + Text( + context.translate(I18n.steps), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + ], + ), + ), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 10, big: 8)), + Text( + '${formatStepsNumber(goal)} ${context.translate(I18n.steps)} · $percentage%', + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + ], + ), + ); + } +} + +class _RingPainter extends CustomPainter { + final double progress; + final Color activeColor; + final Color trackColor; + + _RingPainter({ + required this.progress, + required this.activeColor, + required this.trackColor, + }); + + @override + void paint(Canvas canvas, Size size) { + final center = Offset(size.width / 2, size.height / 2); + final radius = size.width / 2 - 8; + const strokeWidth = 10.0; + + final trackPaint = Paint() + ..color = trackColor + ..style = PaintingStyle.stroke + ..strokeWidth = strokeWidth + ..strokeCap = StrokeCap.round; + + canvas.drawCircle(center, radius, trackPaint); + + final activePaint = Paint() + ..color = activeColor + ..style = PaintingStyle.stroke + ..strokeWidth = strokeWidth + ..strokeCap = StrokeCap.round; + + final sweepAngle = 2 * pi * progress; + canvas.drawArc( + Rect.fromCircle(center: center, radius: radius), + -pi / 2, + sweepAngle, + false, + activePaint, + ); + } + + @override + bool shouldRepaint(_RingPainter oldDelegate) => + oldDelegate.progress != progress || + oldDelegate.activeColor != activeColor || + oldDelegate.trackColor != trackColor; +} diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_stats_row.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_stats_row.dart new file mode 100644 index 00000000..e305a101 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_stats_row.dart @@ -0,0 +1,93 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../format_steps.dart'; +import '../state/activity_meter_view_state.dart'; + +class StepsStatsRow extends StatelessWidget { + final StepsStats stats; + final ThemePort theme; + + const StepsStatsRow({ + super.key, + required this.stats, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + final hasData = stats.total > 0; + + return Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + vertical: SizeUtils.getByScreen(small: 8, big: 6), + ), + child: Row( + children: [ + Expanded( + child: _StatItem( + label: context.translate(I18n.average), + value: hasData ? formatStepsNumber(stats.avgPerDay) : '--', + theme: theme, + ), + ), + Expanded( + child: _StatItem( + label: context.translate(I18n.totalSteps), + value: hasData ? formatStepsNumber(stats.total) : '--', + theme: theme, + ), + ), + Expanded( + child: _StatItem( + label: context.translate(I18n.bestDay), + value: hasData ? formatStepsNumber(stats.bestDaySteps) : '--', + theme: theme, + ), + ), + ], + ), + ); + } +} + +class _StatItem extends StatelessWidget { + final String label; + final String value; + final ThemePort theme; + + const _StatItem({ + required this.label, + required this.value, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Text( + label, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 11, big: 10), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 4, big: 2)), + Text( + value, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 18), + fontWeight: FontWeight.w700, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + ], + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/apps_use/apps_use_builder.dart b/modules/legacy/modules/device_management/lib/src/features/apps_use/apps_use_builder.dart new file mode 100644 index 00000000..608251fb --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/apps_use/apps_use_builder.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import 'presentation/apps_use_screen.dart'; + +class AppsUseBuilder { + const AppsUseBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + return MaterialPage( + key: state.pageKey, + child: const AppsUseScreen(), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/apps_use_screen.dart b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/apps_use_screen.dart new file mode 100644 index 00000000..7e11bacc --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/apps_use_screen.dart @@ -0,0 +1,103 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../../core/presentation/widgets/time_range_selector.dart'; +import 'state/apps_use_view_model.dart'; +import 'widgets/daily_app_usage_section.dart'; +import 'widgets/top_apps_section.dart'; + +class AppsUseScreen extends ConsumerWidget { + const AppsUseScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final state = ref.watch(appsUseViewModelProvider); + final vm = ref.read(appsUseViewModelProvider.notifier); + + ref.listen( + appsUseViewModelProvider.select((s) => s.errorMessage), + (previous, next) { + if (next.isNotEmpty) { + showTopSnackbar(context, message: next, type: MessageType.error); + } + }, + ); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.appsUse), + body: state.isLoading + ? const Center(child: CircularProgressIndicator()) + : SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + TimeRangeSelector( + selected: state.timeRange, + onSelected: (range) => vm.selectTimeRange(range), + onCustomTap: () => _pickCustomRange(context, vm), + theme: theme, + ), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 6)), + if (state.dailyData.isEmpty) + Padding( + padding: EdgeInsets.symmetric( + vertical: SizeUtils.getByScreen(small: 48, big: 40), + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: Center( + child: Text( + context.translate(I18n.noAppUsageData), + style: TextStyle( + fontSize: + SizeUtils.getByScreen(small: 15, big: 14), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + textAlign: TextAlign.center, + ), + ), + ) + else ...[ + TopAppsSection( + apps: state.topApps, + totalDuration: state.totalDuration, + theme: theme, + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 14)), + DailyAppUsageSection( + items: state.dailyData, + hasMore: state.hasMore, + isLoadingMore: state.isLoadingMore, + onLoadMore: () => vm.loadMore(), + theme: theme, + ), + ], + SizedBox(height: SizeUtils.getByScreen(small: 24, big: 20)), + ], + ), + ), + ); + } + + Future _pickCustomRange( + BuildContext context, + AppsUseViewModel vm, + ) async { + final now = DateTime.now(); + final picked = await showDateRangePicker( + context: context, + firstDate: now.subtract(const Duration(days: 365)), + lastDate: now, + ); + if (picked != null) { + vm.selectCustomRange(picked.start, picked.end); + } + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/format_duration.dart b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/format_duration.dart new file mode 100644 index 00000000..e27842ff --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/format_duration.dart @@ -0,0 +1,11 @@ +String formatDuration(int seconds) { + if (seconds < 60) return '${seconds}s'; + + final minutes = seconds ~/ 60; + if (minutes < 60) return '${minutes}min'; + + final hours = minutes ~/ 60; + final remainingMinutes = minutes % 60; + if (remainingMinutes == 0) return '${hours}h'; + return '${hours}h ${remainingMinutes}min'; +} diff --git a/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/state/apps_use_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/state/apps_use_view_model.dart new file mode 100644 index 00000000..8bda74d6 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/state/apps_use_view_model.dart @@ -0,0 +1,271 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; + +import '../../../../core/data/datasources/health_query_builder.dart'; +import '../../../../core/domain/entities/app_usage_time_entity.dart'; +import '../../../../core/domain/repositories/app_usage_times_repository.dart'; +import '../../../../core/presentation/time_range.dart'; +import '../../../../core/providers/app_usage_times_repository_provider.dart'; +import 'apps_use_view_state.dart'; + +final appsUseViewModelProvider = + NotifierProvider.autoDispose( + AppsUseViewModel.new, +); + +class AppsUseViewModel extends Notifier { + late final AppUsageTimesRepository _repository; + + static const int _pageSize = 20; + + @override + AppsUseViewState build() { + _repository = ref.read(appUsageTimesRepositoryProvider); + Future.microtask(_init); + return const AppsUseViewState(); + } + + String? get _identificator => + ref.read(selectedDeviceProvider)?.identificator; + + Future selectTimeRange(TimeRange range) async { + if (range == state.timeRange) return; + state = state.copyWith(timeRange: range, isLoading: true); + await _loadData(); + } + + Future selectCustomRange(DateTime start, DateTime end) async { + state = state.copyWith( + timeRange: TimeRange.custom, + customStart: start, + customEnd: end, + isLoading: true, + ); + await _loadData(); + } + + Future loadMore() async { + if (state.isLoadingMore || !state.hasMore) return; + final identificator = _identificator; + if (identificator == null) return; + + state = state.copyWith(isLoadingMore: true); + + try { + final nextPage = state.currentPage + 1; + final filters = _buildTimeFilters(); + + final items = await _repository.getAppUsageTimes( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + orderField: _timeField, + page: nextPage, + pageSize: _pageSize, + filters: filters, + ), + ); + if (!ref.mounted) return; + + final newDaily = _groupByDay(items); + final merged = _mergeDailyData(state.dailyData, newDaily); + + state = state.copyWith( + dailyData: merged, + currentPage: nextPage, + hasMore: items.length >= _pageSize, + isLoadingMore: false, + ); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith( + isLoadingMore: false, + errorMessage: _formatError(e), + ); + } + } + + Future _init() async { + final identificator = _identificator; + if (identificator == null) { + state = state.copyWith(isLoading: false); + return; + } + + await _loadData(); + } + + Future _loadData() async { + final identificator = _identificator; + if (identificator == null) { + state = state.copyWith(isLoading: false); + return; + } + + try { + final filters = _buildTimeFilters(); + + final items = await _repository.getAppUsageTimes( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + orderField: _timeField, + page: 1, + pageSize: _pageSize, + filters: filters, + ), + ); + if (!ref.mounted) return; + + final dailyData = _groupByDay(items); + final topApps = _computeTopApps(items); + final totalDuration = + items.fold(0, (sum, item) => sum + item.duration); + + state = state.copyWith( + dailyData: dailyData, + topApps: topApps, + totalDuration: totalDuration, + currentPage: 1, + hasMore: items.length >= _pageSize, + isLoading: false, + errorMessage: '', + ); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } + } + + List _groupByDay(List items) { + final Map> groups = {}; + + for (final item in items) { + final date = DateTime.fromMillisecondsSinceEpoch(item.createdAt); + final dayKey = DateTime(date.year, date.month, date.day); + groups.putIfAbsent(dayKey, () => []).add(item); + } + + final sorted = groups.entries.toList() + ..sort((a, b) => b.key.compareTo(a.key)); + + return sorted.map((entry) { + final appMap = {}; + for (final item in entry.value) { + final existing = appMap[item.uid]; + appMap[item.uid] = AppUsageSummary( + uid: item.uid, + name: item.name, + totalDuration: (existing?.totalDuration ?? 0) + item.duration, + ); + } + + final apps = appMap.values.toList() + ..sort((a, b) => b.totalDuration.compareTo(a.totalDuration)); + + final totalDuration = apps.fold(0, (sum, a) => sum + a.totalDuration); + + return DailyAppUsage( + date: entry.key, + apps: apps, + totalDuration: totalDuration, + ); + }).toList(); + } + + List _computeTopApps(List items) { + final Map appMap = {}; + + for (final item in items) { + final existing = appMap[item.uid]; + appMap[item.uid] = AppUsageSummary( + uid: item.uid, + name: item.name, + totalDuration: (existing?.totalDuration ?? 0) + item.duration, + ); + } + + final sorted = appMap.values.toList() + ..sort((a, b) => b.totalDuration.compareTo(a.totalDuration)); + + return sorted.take(5).toList(); + } + + List _mergeDailyData( + List existing, + List newItems, + ) { + final Map merged = { + for (final d in existing) d.date: d, + }; + + for (final d in newItems) { + final existing = merged[d.date]; + if (existing != null) { + final appMap = { + for (final a in existing.apps) a.uid: a, + }; + for (final a in d.apps) { + final prev = appMap[a.uid]; + appMap[a.uid] = AppUsageSummary( + uid: a.uid, + name: a.name, + totalDuration: (prev?.totalDuration ?? 0) + a.totalDuration, + ); + } + final apps = appMap.values.toList() + ..sort((a, b) => b.totalDuration.compareTo(a.totalDuration)); + merged[d.date] = DailyAppUsage( + date: d.date, + apps: apps, + totalDuration: apps.fold(0, (sum, a) => sum + a.totalDuration), + ); + } else { + merged[d.date] = d; + } + } + + final sorted = merged.entries.toList() + ..sort((a, b) => b.key.compareTo(a.key)); + + return sorted.map((e) => e.value).toList(); + } + + static const String _timeField = 'createdAt'; + + List? _buildTimeFilters() { + final range = _getTimeRange(); + if (range == null) return null; + + final (start, end) = range; + return HealthQueryBuilder.timeRangeFilters( + start: start, + end: end, + field: _timeField, + ); + } + + (DateTime, DateTime)? _getTimeRange() { + final now = DateTime.now(); + final todayStart = DateTime(now.year, now.month, now.day); + + switch (state.timeRange) { + case TimeRange.today: + return (todayStart, now); + case TimeRange.sevenDays: + return (todayStart.subtract(const Duration(days: 6)), now); + case TimeRange.thirtyDays: + return (todayStart.subtract(const Duration(days: 29)), now); + case TimeRange.custom: + if (state.customStart != null && state.customEnd != null) { + return (state.customStart!, state.customEnd!); + } + return null; + } + } + + String _formatError(Object e) { + final msg = e.toString(); + return msg.startsWith('Exception: ') ? msg.substring(11) : msg; + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/state/apps_use_view_state.dart b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/state/apps_use_view_state.dart new file mode 100644 index 00000000..10865251 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/state/apps_use_view_state.dart @@ -0,0 +1,40 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../../../core/presentation/time_range.dart'; + +part 'apps_use_view_state.freezed.dart'; + +@freezed +abstract class DailyAppUsage with _$DailyAppUsage { + const factory DailyAppUsage({ + required DateTime date, + required List apps, + required int totalDuration, + }) = _DailyAppUsage; +} + +@freezed +abstract class AppUsageSummary with _$AppUsageSummary { + const factory AppUsageSummary({ + required String uid, + required String name, + required int totalDuration, + }) = _AppUsageSummary; +} + +@freezed +abstract class AppsUseViewState with _$AppsUseViewState { + const factory AppsUseViewState({ + @Default([]) List dailyData, + @Default([]) List topApps, + @Default(0) int totalDuration, + @Default(1) int currentPage, + @Default(false) bool hasMore, + @Default(TimeRange.today) TimeRange timeRange, + DateTime? customStart, + DateTime? customEnd, + @Default(true) bool isLoading, + @Default(false) bool isLoadingMore, + @Default('') String errorMessage, + }) = _AppsUseViewState; +} diff --git a/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/state/apps_use_view_state.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/state/apps_use_view_state.freezed.dart new file mode 100644 index 00000000..c46a38c5 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/state/apps_use_view_state.freezed.dart @@ -0,0 +1,845 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'apps_use_view_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$DailyAppUsage { + + DateTime get date; List get apps; int get totalDuration; +/// Create a copy of DailyAppUsage +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$DailyAppUsageCopyWith get copyWith => _$DailyAppUsageCopyWithImpl(this as DailyAppUsage, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is DailyAppUsage&&(identical(other.date, date) || other.date == date)&&const DeepCollectionEquality().equals(other.apps, apps)&&(identical(other.totalDuration, totalDuration) || other.totalDuration == totalDuration)); +} + + +@override +int get hashCode => Object.hash(runtimeType,date,const DeepCollectionEquality().hash(apps),totalDuration); + +@override +String toString() { + return 'DailyAppUsage(date: $date, apps: $apps, totalDuration: $totalDuration)'; +} + + +} + +/// @nodoc +abstract mixin class $DailyAppUsageCopyWith<$Res> { + factory $DailyAppUsageCopyWith(DailyAppUsage value, $Res Function(DailyAppUsage) _then) = _$DailyAppUsageCopyWithImpl; +@useResult +$Res call({ + DateTime date, List apps, int totalDuration +}); + + + + +} +/// @nodoc +class _$DailyAppUsageCopyWithImpl<$Res> + implements $DailyAppUsageCopyWith<$Res> { + _$DailyAppUsageCopyWithImpl(this._self, this._then); + + final DailyAppUsage _self; + final $Res Function(DailyAppUsage) _then; + +/// Create a copy of DailyAppUsage +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? date = null,Object? apps = null,Object? totalDuration = null,}) { + return _then(_self.copyWith( +date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable +as DateTime,apps: null == apps ? _self.apps : apps // ignore: cast_nullable_to_non_nullable +as List,totalDuration: null == totalDuration ? _self.totalDuration : totalDuration // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [DailyAppUsage]. +extension DailyAppUsagePatterns on DailyAppUsage { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _DailyAppUsage value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _DailyAppUsage() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _DailyAppUsage value) $default,){ +final _that = this; +switch (_that) { +case _DailyAppUsage(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _DailyAppUsage value)? $default,){ +final _that = this; +switch (_that) { +case _DailyAppUsage() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( DateTime date, List apps, int totalDuration)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _DailyAppUsage() when $default != null: +return $default(_that.date,_that.apps,_that.totalDuration);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( DateTime date, List apps, int totalDuration) $default,) {final _that = this; +switch (_that) { +case _DailyAppUsage(): +return $default(_that.date,_that.apps,_that.totalDuration);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( DateTime date, List apps, int totalDuration)? $default,) {final _that = this; +switch (_that) { +case _DailyAppUsage() when $default != null: +return $default(_that.date,_that.apps,_that.totalDuration);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _DailyAppUsage implements DailyAppUsage { + const _DailyAppUsage({required this.date, required final List apps, required this.totalDuration}): _apps = apps; + + +@override final DateTime date; + final List _apps; +@override List get apps { + if (_apps is EqualUnmodifiableListView) return _apps; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_apps); +} + +@override final int totalDuration; + +/// Create a copy of DailyAppUsage +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$DailyAppUsageCopyWith<_DailyAppUsage> get copyWith => __$DailyAppUsageCopyWithImpl<_DailyAppUsage>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _DailyAppUsage&&(identical(other.date, date) || other.date == date)&&const DeepCollectionEquality().equals(other._apps, _apps)&&(identical(other.totalDuration, totalDuration) || other.totalDuration == totalDuration)); +} + + +@override +int get hashCode => Object.hash(runtimeType,date,const DeepCollectionEquality().hash(_apps),totalDuration); + +@override +String toString() { + return 'DailyAppUsage(date: $date, apps: $apps, totalDuration: $totalDuration)'; +} + + +} + +/// @nodoc +abstract mixin class _$DailyAppUsageCopyWith<$Res> implements $DailyAppUsageCopyWith<$Res> { + factory _$DailyAppUsageCopyWith(_DailyAppUsage value, $Res Function(_DailyAppUsage) _then) = __$DailyAppUsageCopyWithImpl; +@override @useResult +$Res call({ + DateTime date, List apps, int totalDuration +}); + + + + +} +/// @nodoc +class __$DailyAppUsageCopyWithImpl<$Res> + implements _$DailyAppUsageCopyWith<$Res> { + __$DailyAppUsageCopyWithImpl(this._self, this._then); + + final _DailyAppUsage _self; + final $Res Function(_DailyAppUsage) _then; + +/// Create a copy of DailyAppUsage +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? date = null,Object? apps = null,Object? totalDuration = null,}) { + return _then(_DailyAppUsage( +date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable +as DateTime,apps: null == apps ? _self._apps : apps // ignore: cast_nullable_to_non_nullable +as List,totalDuration: null == totalDuration ? _self.totalDuration : totalDuration // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +/// @nodoc +mixin _$AppUsageSummary { + + String get uid; String get name; int get totalDuration; +/// Create a copy of AppUsageSummary +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AppUsageSummaryCopyWith get copyWith => _$AppUsageSummaryCopyWithImpl(this as AppUsageSummary, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AppUsageSummary&&(identical(other.uid, uid) || other.uid == uid)&&(identical(other.name, name) || other.name == name)&&(identical(other.totalDuration, totalDuration) || other.totalDuration == totalDuration)); +} + + +@override +int get hashCode => Object.hash(runtimeType,uid,name,totalDuration); + +@override +String toString() { + return 'AppUsageSummary(uid: $uid, name: $name, totalDuration: $totalDuration)'; +} + + +} + +/// @nodoc +abstract mixin class $AppUsageSummaryCopyWith<$Res> { + factory $AppUsageSummaryCopyWith(AppUsageSummary value, $Res Function(AppUsageSummary) _then) = _$AppUsageSummaryCopyWithImpl; +@useResult +$Res call({ + String uid, String name, int totalDuration +}); + + + + +} +/// @nodoc +class _$AppUsageSummaryCopyWithImpl<$Res> + implements $AppUsageSummaryCopyWith<$Res> { + _$AppUsageSummaryCopyWithImpl(this._self, this._then); + + final AppUsageSummary _self; + final $Res Function(AppUsageSummary) _then; + +/// Create a copy of AppUsageSummary +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? uid = null,Object? name = null,Object? totalDuration = null,}) { + return _then(_self.copyWith( +uid: null == uid ? _self.uid : uid // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,totalDuration: null == totalDuration ? _self.totalDuration : totalDuration // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [AppUsageSummary]. +extension AppUsageSummaryPatterns on AppUsageSummary { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AppUsageSummary value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AppUsageSummary() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AppUsageSummary value) $default,){ +final _that = this; +switch (_that) { +case _AppUsageSummary(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AppUsageSummary value)? $default,){ +final _that = this; +switch (_that) { +case _AppUsageSummary() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String uid, String name, int totalDuration)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AppUsageSummary() when $default != null: +return $default(_that.uid,_that.name,_that.totalDuration);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String uid, String name, int totalDuration) $default,) {final _that = this; +switch (_that) { +case _AppUsageSummary(): +return $default(_that.uid,_that.name,_that.totalDuration);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String uid, String name, int totalDuration)? $default,) {final _that = this; +switch (_that) { +case _AppUsageSummary() when $default != null: +return $default(_that.uid,_that.name,_that.totalDuration);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _AppUsageSummary implements AppUsageSummary { + const _AppUsageSummary({required this.uid, required this.name, required this.totalDuration}); + + +@override final String uid; +@override final String name; +@override final int totalDuration; + +/// Create a copy of AppUsageSummary +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AppUsageSummaryCopyWith<_AppUsageSummary> get copyWith => __$AppUsageSummaryCopyWithImpl<_AppUsageSummary>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppUsageSummary&&(identical(other.uid, uid) || other.uid == uid)&&(identical(other.name, name) || other.name == name)&&(identical(other.totalDuration, totalDuration) || other.totalDuration == totalDuration)); +} + + +@override +int get hashCode => Object.hash(runtimeType,uid,name,totalDuration); + +@override +String toString() { + return 'AppUsageSummary(uid: $uid, name: $name, totalDuration: $totalDuration)'; +} + + +} + +/// @nodoc +abstract mixin class _$AppUsageSummaryCopyWith<$Res> implements $AppUsageSummaryCopyWith<$Res> { + factory _$AppUsageSummaryCopyWith(_AppUsageSummary value, $Res Function(_AppUsageSummary) _then) = __$AppUsageSummaryCopyWithImpl; +@override @useResult +$Res call({ + String uid, String name, int totalDuration +}); + + + + +} +/// @nodoc +class __$AppUsageSummaryCopyWithImpl<$Res> + implements _$AppUsageSummaryCopyWith<$Res> { + __$AppUsageSummaryCopyWithImpl(this._self, this._then); + + final _AppUsageSummary _self; + final $Res Function(_AppUsageSummary) _then; + +/// Create a copy of AppUsageSummary +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? uid = null,Object? name = null,Object? totalDuration = null,}) { + return _then(_AppUsageSummary( +uid: null == uid ? _self.uid : uid // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,totalDuration: null == totalDuration ? _self.totalDuration : totalDuration // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +/// @nodoc +mixin _$AppsUseViewState { + + List get dailyData; List get topApps; int get totalDuration; int get currentPage; bool get hasMore; TimeRange get timeRange; DateTime? get customStart; DateTime? get customEnd; bool get isLoading; bool get isLoadingMore; String get errorMessage; +/// Create a copy of AppsUseViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AppsUseViewStateCopyWith get copyWith => _$AppsUseViewStateCopyWithImpl(this as AppsUseViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AppsUseViewState&&const DeepCollectionEquality().equals(other.dailyData, dailyData)&&const DeepCollectionEquality().equals(other.topApps, topApps)&&(identical(other.totalDuration, totalDuration) || other.totalDuration == totalDuration)&&(identical(other.currentPage, currentPage) || other.currentPage == currentPage)&&(identical(other.hasMore, hasMore) || other.hasMore == hasMore)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(dailyData),const DeepCollectionEquality().hash(topApps),totalDuration,currentPage,hasMore,timeRange,customStart,customEnd,isLoading,isLoadingMore,errorMessage); + +@override +String toString() { + return 'AppsUseViewState(dailyData: $dailyData, topApps: $topApps, totalDuration: $totalDuration, currentPage: $currentPage, hasMore: $hasMore, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class $AppsUseViewStateCopyWith<$Res> { + factory $AppsUseViewStateCopyWith(AppsUseViewState value, $Res Function(AppsUseViewState) _then) = _$AppsUseViewStateCopyWithImpl; +@useResult +$Res call({ + List dailyData, List topApps, int totalDuration, int currentPage, bool hasMore, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage +}); + + + + +} +/// @nodoc +class _$AppsUseViewStateCopyWithImpl<$Res> + implements $AppsUseViewStateCopyWith<$Res> { + _$AppsUseViewStateCopyWithImpl(this._self, this._then); + + final AppsUseViewState _self; + final $Res Function(AppsUseViewState) _then; + +/// Create a copy of AppsUseViewState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? dailyData = null,Object? topApps = null,Object? totalDuration = null,Object? currentPage = null,Object? hasMore = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorMessage = null,}) { + return _then(_self.copyWith( +dailyData: null == dailyData ? _self.dailyData : dailyData // ignore: cast_nullable_to_non_nullable +as List,topApps: null == topApps ? _self.topApps : topApps // ignore: cast_nullable_to_non_nullable +as List,totalDuration: null == totalDuration ? _self.totalDuration : totalDuration // ignore: cast_nullable_to_non_nullable +as int,currentPage: null == currentPage ? _self.currentPage : currentPage // ignore: cast_nullable_to_non_nullable +as int,hasMore: null == hasMore ? _self.hasMore : hasMore // ignore: cast_nullable_to_non_nullable +as bool,timeRange: null == timeRange ? _self.timeRange : timeRange // ignore: cast_nullable_to_non_nullable +as TimeRange,customStart: freezed == customStart ? _self.customStart : customStart // ignore: cast_nullable_to_non_nullable +as DateTime?,customEnd: freezed == customEnd ? _self.customEnd : customEnd // ignore: cast_nullable_to_non_nullable +as DateTime?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [AppsUseViewState]. +extension AppsUseViewStatePatterns on AppsUseViewState { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AppsUseViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AppsUseViewState() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AppsUseViewState value) $default,){ +final _that = this; +switch (_that) { +case _AppsUseViewState(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AppsUseViewState value)? $default,){ +final _that = this; +switch (_that) { +case _AppsUseViewState() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( List dailyData, List topApps, int totalDuration, int currentPage, bool hasMore, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AppsUseViewState() when $default != null: +return $default(_that.dailyData,_that.topApps,_that.totalDuration,_that.currentPage,_that.hasMore,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( List dailyData, List topApps, int totalDuration, int currentPage, bool hasMore, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage) $default,) {final _that = this; +switch (_that) { +case _AppsUseViewState(): +return $default(_that.dailyData,_that.topApps,_that.totalDuration,_that.currentPage,_that.hasMore,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List dailyData, List topApps, int totalDuration, int currentPage, bool hasMore, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage)? $default,) {final _that = this; +switch (_that) { +case _AppsUseViewState() when $default != null: +return $default(_that.dailyData,_that.topApps,_that.totalDuration,_that.currentPage,_that.hasMore,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _AppsUseViewState implements AppsUseViewState { + const _AppsUseViewState({final List dailyData = const [], final List topApps = const [], this.totalDuration = 0, this.currentPage = 1, this.hasMore = false, this.timeRange = TimeRange.today, this.customStart, this.customEnd, this.isLoading = true, this.isLoadingMore = false, this.errorMessage = ''}): _dailyData = dailyData,_topApps = topApps; + + + final List _dailyData; +@override@JsonKey() List get dailyData { + if (_dailyData is EqualUnmodifiableListView) return _dailyData; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_dailyData); +} + + final List _topApps; +@override@JsonKey() List get topApps { + if (_topApps is EqualUnmodifiableListView) return _topApps; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_topApps); +} + +@override@JsonKey() final int totalDuration; +@override@JsonKey() final int currentPage; +@override@JsonKey() final bool hasMore; +@override@JsonKey() final TimeRange timeRange; +@override final DateTime? customStart; +@override final DateTime? customEnd; +@override@JsonKey() final bool isLoading; +@override@JsonKey() final bool isLoadingMore; +@override@JsonKey() final String errorMessage; + +/// Create a copy of AppsUseViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AppsUseViewStateCopyWith<_AppsUseViewState> get copyWith => __$AppsUseViewStateCopyWithImpl<_AppsUseViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppsUseViewState&&const DeepCollectionEquality().equals(other._dailyData, _dailyData)&&const DeepCollectionEquality().equals(other._topApps, _topApps)&&(identical(other.totalDuration, totalDuration) || other.totalDuration == totalDuration)&&(identical(other.currentPage, currentPage) || other.currentPage == currentPage)&&(identical(other.hasMore, hasMore) || other.hasMore == hasMore)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_dailyData),const DeepCollectionEquality().hash(_topApps),totalDuration,currentPage,hasMore,timeRange,customStart,customEnd,isLoading,isLoadingMore,errorMessage); + +@override +String toString() { + return 'AppsUseViewState(dailyData: $dailyData, topApps: $topApps, totalDuration: $totalDuration, currentPage: $currentPage, hasMore: $hasMore, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class _$AppsUseViewStateCopyWith<$Res> implements $AppsUseViewStateCopyWith<$Res> { + factory _$AppsUseViewStateCopyWith(_AppsUseViewState value, $Res Function(_AppsUseViewState) _then) = __$AppsUseViewStateCopyWithImpl; +@override @useResult +$Res call({ + List dailyData, List topApps, int totalDuration, int currentPage, bool hasMore, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage +}); + + + + +} +/// @nodoc +class __$AppsUseViewStateCopyWithImpl<$Res> + implements _$AppsUseViewStateCopyWith<$Res> { + __$AppsUseViewStateCopyWithImpl(this._self, this._then); + + final _AppsUseViewState _self; + final $Res Function(_AppsUseViewState) _then; + +/// Create a copy of AppsUseViewState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? dailyData = null,Object? topApps = null,Object? totalDuration = null,Object? currentPage = null,Object? hasMore = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorMessage = null,}) { + return _then(_AppsUseViewState( +dailyData: null == dailyData ? _self._dailyData : dailyData // ignore: cast_nullable_to_non_nullable +as List,topApps: null == topApps ? _self._topApps : topApps // ignore: cast_nullable_to_non_nullable +as List,totalDuration: null == totalDuration ? _self.totalDuration : totalDuration // ignore: cast_nullable_to_non_nullable +as int,currentPage: null == currentPage ? _self.currentPage : currentPage // ignore: cast_nullable_to_non_nullable +as int,hasMore: null == hasMore ? _self.hasMore : hasMore // ignore: cast_nullable_to_non_nullable +as bool,timeRange: null == timeRange ? _self.timeRange : timeRange // ignore: cast_nullable_to_non_nullable +as TimeRange,customStart: freezed == customStart ? _self.customStart : customStart // ignore: cast_nullable_to_non_nullable +as DateTime?,customEnd: freezed == customEnd ? _self.customEnd : customEnd // ignore: cast_nullable_to_non_nullable +as DateTime?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/widgets/daily_app_usage_section.dart b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/widgets/daily_app_usage_section.dart new file mode 100644 index 00000000..2337df83 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/widgets/daily_app_usage_section.dart @@ -0,0 +1,180 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../../../core/presentation/format_date.dart'; +import '../format_duration.dart'; +import '../state/apps_use_view_state.dart'; + +class DailyAppUsageSection extends StatelessWidget { + final List items; + final bool hasMore; + final bool isLoadingMore; + final VoidCallback onLoadMore; + final ThemePort theme; + + const DailyAppUsageSection({ + super.key, + required this.items, + required this.hasMore, + required this.isLoadingMore, + required this.onLoadMore, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: Text( + context.translate(I18n.history), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 14), + fontWeight: FontWeight.w600, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + ), + ...items.map( + (day) => _DailyAppUsageTile(day: day, theme: theme), + ), + if (hasMore) + Padding( + padding: EdgeInsets.all( + SizeUtils.getByScreen(small: 16, big: 14), + ), + child: Center( + child: isLoadingMore + ? const CircularProgressIndicator() + : TextButton( + onPressed: onLoadMore, + child: Text( + context.translate(I18n.loadMore), + style: TextStyle( + color: theme.getColorFor(ThemeCode.legacyPrimary), + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + ], + ); + } +} + +class _DailyAppUsageTile extends StatelessWidget { + final DailyAppUsage day; + final ThemePort theme; + + const _DailyAppUsageTile({ + required this.day, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 22, big: 21), + vertical: SizeUtils.getByScreen(small: 4, big: 3), + ), + child: Container( + padding: EdgeInsets.all( + SizeUtils.getByScreen(small: 14, big: 12), + ), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundSecondary), + borderRadius: BorderRadius.all( + Radius.circular(SizeUtils.getByScreen(small: 12, big: 10)), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + formatDayHeader(context, day.date), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.6), + ), + ), + Text( + formatDuration(day.totalDuration), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 13), + fontWeight: FontWeight.w700, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + ], + ), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 6)), + ...day.apps.take(3).map( + (app) => Padding( + padding: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 4, big: 3), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + app.name, + style: TextStyle( + fontSize: + SizeUtils.getByScreen(small: 12, big: 11), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.7), + ), + overflow: TextOverflow.ellipsis, + ), + ), + Text( + formatDuration(app.totalDuration), + style: TextStyle( + fontSize: + SizeUtils.getByScreen(small: 12, big: 11), + fontWeight: FontWeight.w600, + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + ], + ), + ), + ), + if (day.apps.length > 3) + Padding( + padding: EdgeInsets.only( + top: SizeUtils.getByScreen(small: 2, big: 1), + ), + child: Text( + '+${day.apps.length - 3}', + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 11, big: 10), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.4), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/widgets/top_apps_section.dart b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/widgets/top_apps_section.dart new file mode 100644 index 00000000..f1b64b78 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/apps_use/presentation/widgets/top_apps_section.dart @@ -0,0 +1,135 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../format_duration.dart'; +import '../state/apps_use_view_state.dart'; + +class TopAppsSection extends StatelessWidget { + final List apps; + final int totalDuration; + final ThemePort theme; + + const TopAppsSection({ + super.key, + required this.apps, + required this.totalDuration, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + if (apps.isEmpty) return const SizedBox.shrink(); + + return Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + context.translate(I18n.topApps), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 14), + fontWeight: FontWeight.w600, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + Text( + formatDuration(totalDuration), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 13), + fontWeight: FontWeight.w600, + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), + ), + ], + ), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 6)), + ...apps.map( + (app) => _AppUsageBar( + app: app, + maxDuration: apps.first.totalDuration, + theme: theme, + ), + ), + ], + ), + ); + } +} + +class _AppUsageBar extends StatelessWidget { + final AppUsageSummary app; + final int maxDuration; + final ThemePort theme; + + const _AppUsageBar({ + required this.app, + required this.maxDuration, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + final progress = + maxDuration > 0 ? (app.totalDuration / maxDuration).clamp(0.0, 1.0) : 0.0; + + return Padding( + padding: EdgeInsets.symmetric( + vertical: SizeUtils.getByScreen(small: 4, big: 3), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + app.name, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + color: theme.getColorFor(ThemeCode.textPrimary), + ), + overflow: TextOverflow.ellipsis, + ), + ), + Text( + formatDuration(app.totalDuration), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11), + fontWeight: FontWeight.w600, + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.6), + ), + ), + ], + ), + SizedBox(height: SizeUtils.getByScreen(small: 4, big: 3)), + ClipRRect( + borderRadius: BorderRadius.all( + Radius.circular(SizeUtils.getByScreen(small: 4, big: 3)), + ), + child: LinearProgressIndicator( + value: progress, + minHeight: SizeUtils.getByScreen(small: 6, big: 5), + backgroundColor: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.1), + valueColor: AlwaysStoppedAnimation( + theme.getColorFor(ThemeCode.legacyPrimary), + ), + ), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/contacts/contacts_builder.dart b/modules/legacy/modules/device_management/lib/src/features/contacts/contacts_builder.dart index df0822e7..bd71cc6d 100644 --- a/modules/legacy/modules/device_management/lib/src/features/contacts/contacts_builder.dart +++ b/modules/legacy/modules/device_management/lib/src/features/contacts/contacts_builder.dart @@ -1,9 +1,10 @@ -import 'presentation/contacts_screen.dart'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; import 'package:get_it/get_it.dart'; +import 'package:go_router/go_router.dart'; import 'package:navigation/navigation.dart'; +import 'presentation/contacts_screen.dart'; + class ContactsBuilder { const ContactsBuilder(); diff --git a/modules/legacy/modules/device_management/lib/src/features/contacts/edit_contact_builder.dart b/modules/legacy/modules/device_management/lib/src/features/contacts/edit_contact_builder.dart new file mode 100644 index 00000000..43e3e2bc --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/contacts/edit_contact_builder.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import 'presentation/edit_contact_screen.dart'; + +class EditContactBuilder { + const EditContactBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final contactId = state.pathParameters['contactId']!; + + return MaterialPage( + key: state.pageKey, + child: EditContactScreen(contactId: contactId), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/contacts_screen.dart b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/contacts_screen.dart index 5bb7ab8a..c2d66dbb 100644 --- a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/contacts_screen.dart +++ b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/contacts_screen.dart @@ -1,16 +1,14 @@ import 'package:design_system/design_system.dart'; -import 'package:device_management/src/features/contacts/presentation/widgets/new_contact_dialog.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:device_management/src/features/contacts/domain/entities/contact_entity.dart'; -import 'package:device_management/src/features/contacts/presentation/edit_contact_screen.dart'; -import 'package:device_management/src/features/contacts/presentation/state/contacts_view_model.dart'; import 'package:legacy_shared/legacy_shared.dart'; import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; -import 'widgets/confirm_delete_dialog.dart'; +import 'state/contacts_view_model.dart'; +import 'widgets/contact_card.dart'; +import 'widgets/new_contact_dialog.dart'; class ContactsScreen extends ConsumerWidget { final NavigationContract navigationContract; @@ -21,150 +19,106 @@ class ContactsScreen extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final vm = ref.read(contactsViewModelProvider.notifier); final state = ref.watch(contactsViewModelProvider); - final theme = ref.watch(themePortProvider); + ref.listen( + contactsViewModelProvider.select((s) => s.errorMessage), + (previous, next) { + if (next.isNotEmpty) { + showTopSnackbar(context, message: next, type: MessageType.error); + } + }, + ); + return LegacyPageLayout( theme: theme, title: context.translate(I18n.contacts), showEdit: true, onEditChange: vm.toggleIsEditing, - body: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 8) - ), - child: ListView.separated( - itemBuilder: (BuildContext context, int index)=>ContactCard( - contact: state.contacts[index], - isEditing: state.isEditing, + body: state.isLoading + ? const Center(child: CircularProgressIndicator()) + : state.contacts.isEmpty + ? _EmptyState(theme: theme) + : ListView.separated( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 22, big: 21), + vertical: SizeUtils.getByScreen(small: 10, big: 8), + ), + itemBuilder: (_, index) => ContactCard( + contact: state.contacts[index], + isEditing: state.isEditing, + ), + separatorBuilder: (_, __) => SizedBox( + height: SizeUtils.getByScreen(small: 18, big: 17), + ), + itemCount: state.contacts.length, + ), + footer: Material( + color: theme.getColorFor(ThemeCode.legacyPrimary), + shape: const CircleBorder(), + child: InkWell( + customBorder: const CircleBorder(), + onTap: () => showDialog( + context: context, + builder: (_) => const Dialog( + backgroundColor: Colors.transparent, + child: NewContactDialog(), + ), ), - separatorBuilder: (BuildContext context, int index)=>SizedBox( - height: SizeUtils.getByScreen(small: 18, big: 17) + child: SizedBox( + width: SizeUtils.getByScreen(small: 48, big: 46), + height: SizeUtils.getByScreen(small: 48, big: 46), + child: Icon( + Icons.add, + color: Colors.white, + size: SizeUtils.getByScreen(small: 28, big: 26), + ), ), - itemCount: state.contacts.length - ), - ), - footer: Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: theme.getColorFor(ThemeCode.legacyPrimary), - ), - width: SizeUtils.getByScreen(small: 48, big: 46), - child: CustomTextButton( - onPressed: (){ - showDialog(context: context, builder: (context) => - Dialog( - backgroundColor: Colors.transparent, - child: NewContactDialog(), - ) - ); - }, - text: '+', - color: Colors.white, - size: SizeUtils.getByScreen(small: 48, big: 47), ), ), ); } } -class ContactCard extends ConsumerWidget { +class _EmptyState extends StatelessWidget { + final ThemePort theme; - final ContactEntity contact; - final bool isEditing; - - const ContactCard({ - required this.contact, - required this.isEditing, - }); + const _EmptyState({required this.theme}); @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.watch(themePortProvider); - - return Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 8) - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(SizeUtils.getByScreen(small: 12, big: 18))), - color: theme.getColorFor(ThemeCode.backgroundSecondary), - ), - child: Row( + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: theme.getColorFor(ThemeCode.backgroundPrimary), - ), - padding: EdgeInsets.all(SizeUtils.getByScreen(small: 4, big: 12)), - child: Icon(SFIcons.account, - size: SizeUtils.getByScreen(small: 40, big: 44), - color: theme.getColorFor(ThemeCode.legacyPrimary), - weight: 30, + Icon( + SFIcons.contactsCircle, + size: SizeUtils.getByScreen(small: 64, big: 60), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.3), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 14)), + Text( + context.translate(I18n.contactsEmpty), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 18, big: 17), + fontWeight: FontWeight.w600, + color: theme.getColorFor(ThemeCode.textPrimary), ), ), - SizedBox(width: SizeUtils.getByScreen(small: 16, big: 15)), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(contact.name, - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 18, big: 19), - fontWeight: FontWeight.w500 - ) - ), - Text(contact.phone, - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 14, big: 13), - ) - ) - ], - ) + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 6)), + Text( + context.translate(I18n.contactsEmptyHint), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 13), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), ), - if (isEditing) ...[ - DecoratedBox( - decoration: BoxDecoration( - color: Color(0xFFFF5D52), - borderRadius: BorderRadius.all(Radius.circular(12)), - ), - child: IconButton( - onPressed: (){showDialog(context: context, builder: (context)=>Dialog( - child: ConfirmDeleteDialog(contact: contact), - ));}, - icon: Icon( - Icons.close, - color: Colors.white, - ), - ), - ), - SizedBox(width: SizeUtils.getByScreen(small: 16, big: 14)), - DecoratedBox( - decoration: BoxDecoration( - color: theme.getColorFor(ThemeCode.legacyPrimary), - borderRadius: BorderRadius.all(Radius.circular(12)), - ), - child: - IconButton( - onPressed: (){Navigator.push( - context, - MaterialPageRoute(builder: (_) => EditContactScreen( - contact: contact, - /*navigationContract: navigationContract*/ - )), - );}, - icon: Icon( - Icons.edit_outlined, - color: Colors.white, - ), - ), - ), - ] ], ), ); } -} \ No newline at end of file +} diff --git a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/edit_contact_screen.dart b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/edit_contact_screen.dart index 3d89122f..d16f05b6 100644 --- a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/edit_contact_screen.dart +++ b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/edit_contact_screen.dart @@ -2,25 +2,48 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:device_management/src/features/contacts/domain/entities/contact_entity.dart'; -import 'package:device_management/src/features/contacts/presentation/state/contacts_view_model.dart'; -// import 'package:navigation/navigation.dart'; +import 'package:get_it/get_it.dart'; +import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; -class EditContactScreen extends ConsumerWidget { - //final NavigationContract navigationContract; - final ContactEntity contact; +import '../domain/entities/contact_entity.dart'; +import 'state/contacts_view_model.dart'; - const EditContactScreen({super.key, required this.contact -// required this.navigationContract -}); +class EditContactScreen extends ConsumerStatefulWidget { + final String contactId; + + const EditContactScreen({super.key, required this.contactId}); @override - Widget build(BuildContext context, WidgetRef ref) { - final vm = ref.read(contactsViewModelProvider.notifier); - // final state = ref.watch(linkedDevicesViewModelProvider); + ConsumerState createState() => _EditContactScreenState(); +} +class _EditContactScreenState extends ConsumerState { + late final ContactEntity _contact; + late final TextEditingController _nameController; + late final TextEditingController _phoneController; + + @override + void initState() { + super.initState(); + _contact = ref + .read(contactsViewModelProvider) + .contacts + .firstWhere((c) => c.id == widget.contactId); + _nameController = TextEditingController(text: _contact.name); + _phoneController = TextEditingController(text: _contact.phone); + } + + @override + void dispose() { + _nameController.dispose(); + _phoneController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { final theme = ref.watch(themePortProvider); return Scaffold( @@ -29,132 +52,84 @@ class EditContactScreen extends ConsumerWidget { child: Column( children: [ Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 8) + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 22, big: 21), + vertical: SizeUtils.getByScreen(small: 10, big: 8), ), child: Stack( children: [ - IconButton(onPressed: () {Navigator.pop(context);}, - icon: Icon(Icons.arrow_back)), + IconButton( + onPressed: () => GetIt.I().goBack(), + icon: const Icon(Icons.arrow_back), + ), Center( - child: Text(context.translate('Edit Contact'), + child: Text( + context.translate(I18n.editContact), style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 28, big: 27) + fontSize: SizeUtils.getByScreen(small: 28, big: 27), ), - ) - ) + ), + ), ], ), ), SizedBox(height: SizeUtils.getByScreen(small: 20, big: 18)), - Expanded(child: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 48, vertical: 10), - big: EdgeInsets.symmetric(horizontal: 47, vertical: 8) - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Stack( - children: [ - Center(child: SvgPicture.asset('assets/images/ui/profile.svg')), - Center(child: SizedBox( - width: 160, - height: 160, - child: Align(alignment: Alignment.bottomRight, - child: IconButton( - onPressed: (){}, - icon: Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Color(0xFFCAC9C9) - ), - padding: EdgeInsets.all(8), - child: Icon( - Icons.edit_outlined, - color: Colors.white, - size: SizeUtils.getByScreen(small: 32, big: 30), - ), - ), - ) - ) - )) - ], - ), - SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)), - CustomTextField( - controller: vm.nameController, - hint: contact.name, - label: context.translate(I18n.name), - ), - SizedBox(height: SizeUtils.getByScreen(small: 28, big: 26)), - Stack( - children: [ - CustomTextField( - controller: vm.phoneController, - keyboardType: TextInputType.number, - hint: contact.phone, - label: context.translate('Phone number'), + Expanded( + child: Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 48, big: 47), + vertical: SizeUtils.getByScreen(small: 10, big: 8), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Center( + child: SvgPicture.asset( + 'assets/shared/images/profile.svg', ), - SizedBox( - height: SizeUtils.getByScreen(small: 90, big: 85), - child: Align( - alignment: Alignment.bottomRight, - child: IconButton( - onPressed: (){}, - icon: DecoratedBox( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: theme.getColorFor(ThemeCode.legacyPrimary) - ), - child: Icon( - SFIcons.contactsCircle, - color: Colors.white, - size: SizeUtils.getByScreen(small: 40, big: 38), - ) - ) - ), - ), - ), - ], - ) - ], - ), - PrimaryButton( - onPressed: () async { - await vm.updateContact(contact); - - final errorMessage = ref.read( - contactsViewModelProvider.select((s)=>s.errorMessage) - ); - if (errorMessage.isNotEmpty) { - showTopSnackbar( - context, - message: errorMessage, - type: MessageType.error + ), + SizedBox( + height: SizeUtils.getByScreen(small: 24, big: 22), + ), + CustomTextField( + controller: _nameController, + label: context.translate(I18n.name), + ), + SizedBox( + height: SizeUtils.getByScreen(small: 28, big: 26), + ), + CustomTextField( + controller: _phoneController, + keyboardType: TextInputType.number, + label: context.translate(I18n.phoneNumber), + ), + ], + ), + PrimaryButton( + onPressed: () async { + final vm = + ref.read(contactsViewModelProvider.notifier); + final success = await vm.updateContact( + contact: _contact, + name: _nameController.text, + phone: _phoneController.text, ); - return; - } - - final isComplete = ref.read( - contactsViewModelProvider.select((s)=>s.isComplete) - ); - if (isComplete){ - Navigator.pop(context); - } - }, - text: context.translate(I18n.save), - color: theme.getColorFor(ThemeCode.legacyPrimary) - ) - ], - )) + if (success && mounted) { + GetIt.I().goBack(); + } + }, + text: context.translate(I18n.save), + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), + ], + ), + ), ), ], - ) + ), ), ); } diff --git a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_model.dart index 5b8313de..fceb2eb8 100644 --- a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_model.dart +++ b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_model.dart @@ -1,208 +1,174 @@ -import 'package:device_management/src/core/data/models/update_contact_request_model.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:device_management/src/features/contacts/domain/entities/contact_entity.dart'; -import 'package:device_management/src/features/contacts/presentation/state/contacts_view_state.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; import 'package:sf_shared/sf_shared.dart'; +import 'package:uuid/uuid.dart'; import '../../../../core/data/models/create_contact_request_model.dart'; +import '../../../../core/data/models/update_contact_request_model.dart'; import '../../../../core/domain/repositories/contacts_repository.dart'; import '../../../../core/providers/contacts_repository_provider.dart'; +import '../../domain/entities/contact_entity.dart'; +import 'contacts_view_state.dart'; final contactsViewModelProvider = -NotifierProvider.autoDispose( + NotifierProvider.autoDispose( ContactsViewModel.new, ); class ContactsViewModel extends Notifier { - static final RegExp _phoneRegex = RegExp(r'^\+?\d{6,15}$'); + static const _uuid = Uuid(); late final ContactsRepository _contactsRepository; - late final TextEditingController nameController; - late final TextEditingController phoneController; - @override ContactsViewState build() { _contactsRepository = ref.read(contactsRepositoryProvider); - - _initControllers(); _init(); - return const ContactsViewState(); } - void _initControllers() { - nameController = TextEditingController(); - phoneController = TextEditingController(); - - nameController.addListener(_onNameChanged); - phoneController.addListener(_onPhoneChanged); - - ref.onDispose(disposeControllers); - } - Future _init() async { - final user = await ref.read(userInfoProvider.future); + try { + final user = await ref.read(userInfoProvider.future); + if (!ref.mounted) return; - final contacts = await _contactsRepository.getContacts(userId: user.id); - state = state.copyWith( - contacts: contacts, - isLoading: false, - ); - } + final contacts = + await _contactsRepository.getContacts(userId: user.id); + if (!ref.mounted) return; - void setContacts(List contacts) { - state = state.copyWith( - contacts: contacts - ); + state = state.copyWith(contacts: contacts, isLoading: false); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } } void toggleIsEditing() { state = state.copyWith(isEditing: !state.isEditing); } - void _onNameChanged() { - final text = nameController.text; - if (text == state.name) return; + Future createContact({ + required String name, + required String phone, + }) async { + if (state.isLoading) return false; - state = state.copyWith(name: text, errorMessage: ''); - } - - void _onPhoneChanged() { - final text = phoneController.text; - if (text == state.phone) return; - - state = state.copyWith(phone: text, errorMessage: ''); - } - - void updateDialCode(String dialCode) { - state = state.copyWith(dialCode: dialCode, errorMessage: ''); - } - - Future updateContact(ContactEntity contact) async { - if (state.isLoading) return; - if (state.errorMessage.isNotEmpty) return; - - try { + if (phone.isEmpty) { state = state.copyWith( - isLoading: true, - isComplete: false - ); - - final name = state.name; - final phone = state.phone; - final dialCode = state.dialCode; - - if (name.isEmpty && phone.isEmpty) { - state = state.copyWith(isLoading: false); - return; - } - - if (phone.isNotEmpty && !_phoneRegex.hasMatch(phone)) { - state = state.copyWith( - isLoading: false, - errorMessage: 'errorMessagePhoneIsInvalid' - ); - return; - } - - final request = UpdateContactRequestModel( - id: contact.id, - name: name.isEmpty? contact.name : name, - phone: phone.isEmpty? contact.phone : dialCode + phone - ); - - final user = await ref.read(userInfoProvider.future); - - _contactsRepository.updateContact(userId: user.id, request: request); - - state = state.copyWith( - isLoading: false, - isComplete: true - ); - } catch(e) { - state = state.copyWith( - isLoading: false, - errorMessage: e.toString() + errorMessage: I18n.errorMessagePhoneIsInvalid.tr(), ); + return false; } - } - - Future createContact() async { - if (state.isLoading) return; - if (state.errorMessage.isNotEmpty) return; try { - state = state.copyWith( - isLoading: true, - isComplete: false - ); - - final name = state.name; - final phone = state.phone; - - if (!_phoneRegex.hasMatch(phone)) { - state = state.copyWith(errorMessage: 'errorMessagePhoneIsInvalid'); - return; - } + state = state.copyWith(isLoading: true, errorMessage: ''); final user = await ref.read(userInfoProvider.future); + if (!ref.mounted) return false; - final request = ContactRequestModel( - id: '', + final request = CreateContactRequestModel( + id: _uuid.v4(), name: name, phone: phone, userId: user.id, ); - _contactsRepository.createContact(request: request); + await _contactsRepository.createContact(request: request); + if (!ref.mounted) return false; - state = state.copyWith( - isLoading: false, - isComplete: true - ); - } catch(e) { - state = state.copyWith( - isLoading: false, - errorMessage: e.toString() - ); + await _reload(); + return true; + } catch (e) { + if (!ref.mounted) return false; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + return false; } } - Future deleteContact(ContactEntity contact) async { + Future updateContact({ + required ContactEntity contact, + required String name, + required String phone, + }) async { + if (state.isLoading) return false; - if (state.isLoading) return; + if (name.isEmpty && phone.isEmpty) return false; try { - state = state.copyWith( - isLoading: true, - isComplete: false, + state = state.copyWith(isLoading: true, errorMessage: ''); + + final request = UpdateContactRequestModel( + id: contact.id, + name: name.isEmpty ? contact.name : name, + phone: phone.isEmpty ? contact.phone : phone, ); + await _contactsRepository.updateContact(request: request); + if (!ref.mounted) return false; + + await _reload(); + return true; + } catch (e) { + if (!ref.mounted) return false; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + return false; + } + } + + Future deleteContact(ContactEntity contact) async { + if (state.isLoading) return false; + + try { + state = state.copyWith(isLoading: true, errorMessage: ''); + await _contactsRepository.deleteContact(contactId: contact.id); + if (!ref.mounted) return false; - state = state.copyWith( - isLoading: false, - isComplete: true, - ); - - ref.invalidateSelf(); - - } catch(e) { - state = state.copyWith( - isLoading: false, - errorMessage: e.toString() - ); + await _reload(); + return true; + } catch (e) { + if (!ref.mounted) return false; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + return false; } - } - void disposeControllers() { - nameController.removeListener(_onNameChanged); - phoneController.removeListener(_onPhoneChanged); + Future _reload() async { + try { + final user = await ref.read(userInfoProvider.future); + if (!ref.mounted) return; - nameController.dispose(); - phoneController.dispose(); + final contacts = + await _contactsRepository.getContacts(userId: user.id); + if (!ref.mounted) return; + + state = state.copyWith(contacts: contacts, isLoading: false); + + _syncToDevice(user.id, contacts); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } + } + + Future _syncToDevice(String userId, List contacts) async { + final device = ref.read(selectedDeviceProvider); + if (device == null) return; + + try { + await _contactsRepository.syncContactsToDevice( + userId: userId, + deviceId: device.id, + contacts: contacts, + ); + } catch (_) { + // Sync failure is non-blocking — contacts were already saved via CRUD + } + } + + String _formatError(Object e) { + final msg = e.toString(); + return msg.startsWith('Exception: ') ? msg.substring(11) : msg; } } diff --git a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_state.dart b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_state.dart index 186f2d3b..5411421a 100644 --- a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_state.dart +++ b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_state.dart @@ -1,5 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:device_management/src/features/contacts/domain/entities/contact_entity.dart'; + +import '../../domain/entities/contact_entity.dart'; part 'contacts_view_state.freezed.dart'; @@ -7,12 +8,8 @@ part 'contacts_view_state.freezed.dart'; abstract class ContactsViewState with _$ContactsViewState { const factory ContactsViewState({ @Default([]) List contacts, - @Default(false) bool isLoading, - @Default(false) bool isComplete, + @Default(true) bool isLoading, @Default(false) bool isEditing, - @Default('') String name, - @Default('') String phone, - @Default('+34') String dialCode, @Default('') String errorMessage, }) = _ContactsViewState; } diff --git a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_state.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_state.freezed.dart index 903be8ce..5b1b4395 100644 --- a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_state.freezed.dart +++ b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/state/contacts_view_state.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$ContactsViewState { - List get contacts; bool get isLoading; bool get isComplete; bool get isEditing; String get name; String get phone; String get dialCode; String get errorMessage; + List get contacts; bool get isLoading; bool get isEditing; String get errorMessage; /// Create a copy of ContactsViewState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $ContactsViewStateCopyWith get copyWith => _$ContactsViewStat @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is ContactsViewState&&const DeepCollectionEquality().equals(other.contacts, contacts)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.isEditing, isEditing) || other.isEditing == isEditing)&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is ContactsViewState&&const DeepCollectionEquality().equals(other.contacts, contacts)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isEditing, isEditing) || other.isEditing == isEditing)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(contacts),isLoading,isComplete,isEditing,name,phone,dialCode,errorMessage); +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(contacts),isLoading,isEditing,errorMessage); @override String toString() { - return 'ContactsViewState(contacts: $contacts, isLoading: $isLoading, isComplete: $isComplete, isEditing: $isEditing, name: $name, phone: $phone, dialCode: $dialCode, errorMessage: $errorMessage)'; + return 'ContactsViewState(contacts: $contacts, isLoading: $isLoading, isEditing: $isEditing, errorMessage: $errorMessage)'; } @@ -45,7 +45,7 @@ abstract mixin class $ContactsViewStateCopyWith<$Res> { factory $ContactsViewStateCopyWith(ContactsViewState value, $Res Function(ContactsViewState) _then) = _$ContactsViewStateCopyWithImpl; @useResult $Res call({ - List contacts, bool isLoading, bool isComplete, bool isEditing, String name, String phone, String dialCode, String errorMessage + List contacts, bool isLoading, bool isEditing, String errorMessage }); @@ -62,16 +62,12 @@ class _$ContactsViewStateCopyWithImpl<$Res> /// Create a copy of ContactsViewState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? contacts = null,Object? isLoading = null,Object? isComplete = null,Object? isEditing = null,Object? name = null,Object? phone = null,Object? dialCode = null,Object? errorMessage = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? contacts = null,Object? isLoading = null,Object? isEditing = null,Object? errorMessage = null,}) { return _then(_self.copyWith( contacts: null == contacts ? _self.contacts : contacts // ignore: cast_nullable_to_non_nullable as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable -as bool,isComplete: null == isComplete ? _self.isComplete : isComplete // ignore: cast_nullable_to_non_nullable as bool,isEditing: null == isEditing ? _self.isEditing : isEditing // ignore: cast_nullable_to_non_nullable -as bool,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable -as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable -as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable -as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String, )); } @@ -157,10 +153,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( List contacts, bool isLoading, bool isComplete, bool isEditing, String name, String phone, String dialCode, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( List contacts, bool isLoading, bool isEditing, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _ContactsViewState() when $default != null: -return $default(_that.contacts,_that.isLoading,_that.isComplete,_that.isEditing,_that.name,_that.phone,_that.dialCode,_that.errorMessage);case _: +return $default(_that.contacts,_that.isLoading,_that.isEditing,_that.errorMessage);case _: return orElse(); } @@ -178,10 +174,10 @@ return $default(_that.contacts,_that.isLoading,_that.isComplete,_that.isEditing, /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( List contacts, bool isLoading, bool isComplete, bool isEditing, String name, String phone, String dialCode, String errorMessage) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( List contacts, bool isLoading, bool isEditing, String errorMessage) $default,) {final _that = this; switch (_that) { case _ContactsViewState(): -return $default(_that.contacts,_that.isLoading,_that.isComplete,_that.isEditing,_that.name,_that.phone,_that.dialCode,_that.errorMessage);case _: +return $default(_that.contacts,_that.isLoading,_that.isEditing,_that.errorMessage);case _: throw StateError('Unexpected subclass'); } @@ -198,10 +194,10 @@ return $default(_that.contacts,_that.isLoading,_that.isComplete,_that.isEditing, /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( List contacts, bool isLoading, bool isComplete, bool isEditing, String name, String phone, String dialCode, String errorMessage)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List contacts, bool isLoading, bool isEditing, String errorMessage)? $default,) {final _that = this; switch (_that) { case _ContactsViewState() when $default != null: -return $default(_that.contacts,_that.isLoading,_that.isComplete,_that.isEditing,_that.name,_that.phone,_that.dialCode,_that.errorMessage);case _: +return $default(_that.contacts,_that.isLoading,_that.isEditing,_that.errorMessage);case _: return null; } @@ -213,7 +209,7 @@ return $default(_that.contacts,_that.isLoading,_that.isComplete,_that.isEditing, class _ContactsViewState implements ContactsViewState { - const _ContactsViewState({final List contacts = const [], this.isLoading = false, this.isComplete = false, this.isEditing = false, this.name = '', this.phone = '', this.dialCode = '+34', this.errorMessage = ''}): _contacts = contacts; + const _ContactsViewState({final List contacts = const [], this.isLoading = true, this.isEditing = false, this.errorMessage = ''}): _contacts = contacts; final List _contacts; @@ -224,11 +220,7 @@ class _ContactsViewState implements ContactsViewState { } @override@JsonKey() final bool isLoading; -@override@JsonKey() final bool isComplete; @override@JsonKey() final bool isEditing; -@override@JsonKey() final String name; -@override@JsonKey() final String phone; -@override@JsonKey() final String dialCode; @override@JsonKey() final String errorMessage; /// Create a copy of ContactsViewState @@ -241,16 +233,16 @@ _$ContactsViewStateCopyWith<_ContactsViewState> get copyWith => __$ContactsViewS @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _ContactsViewState&&const DeepCollectionEquality().equals(other._contacts, _contacts)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.isEditing, isEditing) || other.isEditing == isEditing)&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ContactsViewState&&const DeepCollectionEquality().equals(other._contacts, _contacts)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isEditing, isEditing) || other.isEditing == isEditing)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_contacts),isLoading,isComplete,isEditing,name,phone,dialCode,errorMessage); +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_contacts),isLoading,isEditing,errorMessage); @override String toString() { - return 'ContactsViewState(contacts: $contacts, isLoading: $isLoading, isComplete: $isComplete, isEditing: $isEditing, name: $name, phone: $phone, dialCode: $dialCode, errorMessage: $errorMessage)'; + return 'ContactsViewState(contacts: $contacts, isLoading: $isLoading, isEditing: $isEditing, errorMessage: $errorMessage)'; } @@ -261,7 +253,7 @@ abstract mixin class _$ContactsViewStateCopyWith<$Res> implements $ContactsViewS factory _$ContactsViewStateCopyWith(_ContactsViewState value, $Res Function(_ContactsViewState) _then) = __$ContactsViewStateCopyWithImpl; @override @useResult $Res call({ - List contacts, bool isLoading, bool isComplete, bool isEditing, String name, String phone, String dialCode, String errorMessage + List contacts, bool isLoading, bool isEditing, String errorMessage }); @@ -278,16 +270,12 @@ class __$ContactsViewStateCopyWithImpl<$Res> /// Create a copy of ContactsViewState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? contacts = null,Object? isLoading = null,Object? isComplete = null,Object? isEditing = null,Object? name = null,Object? phone = null,Object? dialCode = null,Object? errorMessage = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? contacts = null,Object? isLoading = null,Object? isEditing = null,Object? errorMessage = null,}) { return _then(_ContactsViewState( contacts: null == contacts ? _self._contacts : contacts // ignore: cast_nullable_to_non_nullable as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable -as bool,isComplete: null == isComplete ? _self.isComplete : isComplete // ignore: cast_nullable_to_non_nullable as bool,isEditing: null == isEditing ? _self.isEditing : isEditing // ignore: cast_nullable_to_non_nullable -as bool,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable -as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable -as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable -as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String, )); } diff --git a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/widgets/confirm_delete_dialog.dart b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/widgets/confirm_delete_dialog.dart index a5e25700..04bec054 100644 --- a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/widgets/confirm_delete_dialog.dart +++ b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/widgets/confirm_delete_dialog.dart @@ -1,81 +1,74 @@ import 'package:design_system/design_system.dart'; -import 'package:device_management/src/features/contacts/domain/entities/contact_entity.dart'; -import 'package:device_management/src/features/contacts/presentation/state/contacts_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; -class ConfirmDeleteDialog extends ConsumerWidget { +import '../../domain/entities/contact_entity.dart'; +import '../state/contacts_view_model.dart'; +class ConfirmDeleteDialog extends ConsumerWidget { final ContactEntity contact; - const ConfirmDeleteDialog({required this.contact}); + const ConfirmDeleteDialog({super.key, required this.contact}); @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - final vm = ref.read(contactsViewModelProvider.notifier); + final theme = ref.watch(themePortProvider); return Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 32, vertical: 30), - big: EdgeInsets.symmetric(horizontal: 30, vertical: 28) + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 32, big: 30), + vertical: SizeUtils.getByScreen(small: 30, big: 28), + ), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundPrimary), + borderRadius: BorderRadius.circular( + SizeUtils.getByScreen(small: 12, big: 10), + ), ), width: SizeUtils.getByScreen(small: 360, big: 350), - height: SizeUtils.getByScreen(small: 195, big: 185), child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Text(context.translate(I18n.deleteContactMessage), + Text( + context.translate(I18n.deleteContactMessage), textAlign: TextAlign.center, - style: TextStyle(fontSize: SizeUtils.getByScreen(small: 19, big: 18)), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 19, big: 18), + ), ), SizedBox(height: SizeUtils.getByScreen(small: 28, big: 27)), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded(child: PrimaryButton( - onPressed: (){Navigator.pop(context);}, - text: context.translate(I18n.cancel), - color: theme.getColorFor(ThemeCode.legacyPrimary), - height: SizeUtils.getByScreen(small: 38, big: 36), - radius: SizeUtils.getByScreen(small: 32, big: 34), - )), + Expanded( + child: PrimaryButton( + onPressed: () => Navigator.pop(context), + text: context.translate(I18n.cancel), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: SizeUtils.getByScreen(small: 38, big: 36), + radius: SizeUtils.getByScreen(small: 32, big: 34), + ), + ), SizedBox(width: SizeUtils.getByScreen(small: 4, big: 16)), - Expanded(child: PrimaryButton( - onPressed: () async { - await vm.deleteContact(contact); - - final errorMessage = ref.read( - contactsViewModelProvider.select((s)=>s.errorMessage) - ); - if (errorMessage.isNotEmpty) { - showTopSnackbar( - context, - message: errorMessage, - type: MessageType.error - ); - } - - final isComplete = ref.read( - contactsViewModelProvider.select((s)=>s.isComplete) - ); - if (isComplete) { - Navigator.pop(context); - } - - }, - text: context.translate(I18n.delete), - color: theme.getColorFor(ThemeCode.legacyPrimary), - height: SizeUtils.getByScreen(small: 38, big: 36), - radius: SizeUtils.getByScreen(small: 32, big: 34), - )) + Expanded( + child: PrimaryButton( + onPressed: () async { + final vm = ref.read(contactsViewModelProvider.notifier); + final success = await vm.deleteContact(contact); + if (success && context.mounted) Navigator.pop(context); + }, + text: context.translate(I18n.delete), + color: const Color(0xFFFF5D52), + height: SizeUtils.getByScreen(small: 38, big: 36), + radius: SizeUtils.getByScreen(small: 32, big: 34), + ), + ), ], - ) + ), ], ), ); } - -} \ No newline at end of file +} diff --git a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/widgets/contact_card.dart b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/widgets/contact_card.dart new file mode 100644 index 00000000..ccc828e3 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/widgets/contact_card.dart @@ -0,0 +1,108 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:get_it/get_it.dart'; +import 'package:navigation/navigation.dart'; +import 'package:utils/utils.dart'; + +import '../../domain/entities/contact_entity.dart'; +import 'confirm_delete_dialog.dart'; + +class ContactCard extends ConsumerWidget { + final ContactEntity contact; + final bool isEditing; + + const ContactCard({ + super.key, + required this.contact, + required this.isEditing, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + return Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 22, big: 21), + vertical: SizeUtils.getByScreen(small: 10, big: 8), + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(SizeUtils.getByScreen(small: 12, big: 18)), + ), + color: theme.getColorFor(ThemeCode.backgroundSecondary), + ), + child: Row( + children: [ + Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: theme.getColorFor(ThemeCode.backgroundPrimary), + ), + padding: + EdgeInsets.all(SizeUtils.getByScreen(small: 4, big: 12)), + child: Icon( + SFIcons.account, + size: SizeUtils.getByScreen(small: 40, big: 44), + color: theme.getColorFor(ThemeCode.legacyPrimary), + weight: 30, + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 16, big: 15)), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + contact.name, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 18, big: 19), + fontWeight: FontWeight.w500, + ), + ), + Text( + contact.phone, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 13), + ), + ), + ], + ), + ), + if (isEditing) ...[ + DecoratedBox( + decoration: BoxDecoration( + color: const Color(0xFFFF5D52), + borderRadius: BorderRadius.all(Radius.circular(12)), + ), + child: IconButton( + onPressed: () => showDialog( + context: context, + builder: (_) => Dialog( + child: ConfirmDeleteDialog(contact: contact), + ), + ), + icon: const Icon(Icons.close, color: Colors.white), + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 16, big: 14)), + DecoratedBox( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.legacyPrimary), + borderRadius: BorderRadius.all(Radius.circular(12)), + ), + child: IconButton( + onPressed: () { + final nav = GetIt.I(); + nav.pushTo(AppRoutes.editContactPath(contact.id)); + }, + icon: const Icon(Icons.edit_outlined, color: Colors.white), + ), + ), + ], + ], + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/widgets/new_contact_dialog.dart b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/widgets/new_contact_dialog.dart index 5d0dbb9e..e907266b 100644 --- a/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/widgets/new_contact_dialog.dart +++ b/modules/legacy/modules/device_management/lib/src/features/contacts/presentation/widgets/new_contact_dialog.dart @@ -1,115 +1,146 @@ import 'package:design_system/design_system.dart'; -import 'package:country_code_picker/country_code_picker.dart'; -import 'package:device_management/src/features/contacts/presentation/state/contacts_view_model.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_contacts/flutter_contacts.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; -class NewContactDialog extends ConsumerWidget { +import '../state/contacts_view_model.dart'; - const NewContactDialog(); +class NewContactDialog extends ConsumerStatefulWidget { + const NewContactDialog({super.key}); @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); + ConsumerState createState() => _NewContactDialogState(); +} - final vm = ref.read(contactsViewModelProvider.notifier); - final state = ref.watch(contactsViewModelProvider); +class _NewContactDialogState extends ConsumerState { + final _nameController = TextEditingController(); + final _phoneController = TextEditingController(); + + @override + void dispose() { + _nameController.dispose(); + _phoneController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final theme = ref.watch(themePortProvider); return Container( - padding: EdgeInsets.symmetric(horizontal: 10, vertical: 10), - height: 430, - width: 400, + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 10, big: 8), + vertical: SizeUtils.getByScreen(small: 10, big: 8), + ), + height: SizeUtils.getByScreen(small: 430, big: 410), + width: SizeUtils.getByScreen(small: 400, big: 390), decoration: BoxDecoration( color: theme.getColorFor(ThemeCode.backgroundPrimary), - borderRadius: BorderRadius.all(Radius.circular(6)) + borderRadius: BorderRadius.all( + Radius.circular(SizeUtils.getByScreen(small: 6, big: 5)), + ), ), - child: Column( - children: [ - Stack( - children: [ - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: (){Navigator.pop(context);}, - icon: Icon(Icons.close, - color: theme.getColorFor(ThemeCode.legacyPrimary), + child: SingleChildScrollView( + child: Column( + children: [ + Stack( + children: [ + Align( + alignment: Alignment.topRight, + child: IconButton( + onPressed: () => Navigator.pop(context), + icon: Icon( + Icons.close, + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), ), ), - ), - Center( - child: Text(context.translate(I18n.newContact).toUpperCase(), - style: TextStyle( - color: theme.getColorFor(ThemeCode.legacyPrimary), - fontWeight: FontWeight.w500 + Center( + child: Text( + context.translate(I18n.newContact).toUpperCase(), + style: TextStyle( + color: theme.getColorFor(ThemeCode.legacyPrimary), + fontWeight: FontWeight.w500, + ), ), ), - ) - ], - ), - SizedBox( - height: 120, - child: SvgPicture.asset('assets/shared/images/profile.svg'), - ), - SizedBox(height: 14), - CustomTextField( - hint: context.translate(I18n.name), - controller: vm.nameController, - ), - SizedBox(height: 14), - Row( - spacing: 10, - children: [ - CountryPrefixPicker( - headerText: context.translate(I18n.selectYourCountry), - onChanged: (CountryCode value) { - vm.updateDialCode(value.dialCode ?? state.dialCode); - }, - ), - Expanded( - child: CustomTextField( - controller: vm.phoneController, - hint: context.translate(I18n.phoneNumber), - keyboardType: TextInputType.number, - ), - ), - ], - ), - SizedBox(height: 14), - Padding( - padding: EdgeInsets.symmetric(horizontal: 24, vertical: 10), - child: PrimaryButton( - onPressed: () async { - await vm.createContact(); - - final errorMessage = ref.read( - contactsViewModelProvider.select((s)=>s.errorMessage) - ); - if (errorMessage.isNotEmpty){ - showTopSnackbar( - context, - message: errorMessage, - type: MessageType.error - ); - return; - } - - final isComplete = ref.read( - contactsViewModelProvider.select((s)=>s.isComplete) - ); - if (isComplete) { - Navigator.pop(context); - } - }, - text: context.translate(I18n.save), - color: theme.getColorFor(ThemeCode.legacyPrimary) + ], ), - ), - ], + SizedBox( + height: SizeUtils.getByScreen(small: 120, big: 110), + child: SvgPicture.asset('assets/shared/images/profile.svg'), + ), + SizedBox(height: SizeUtils.getByScreen(small: 14, big: 12)), + CustomTextField( + hint: context.translate(I18n.name), + controller: _nameController, + ), + SizedBox(height: SizeUtils.getByScreen(small: 14, big: 12)), + Row( + spacing: SizeUtils.getByScreen(small: 10, big: 8), + children: [ + Expanded( + child: CustomTextField( + controller: _phoneController, + hint: context.translate(I18n.phoneNumber), + keyboardType: TextInputType.phone, + readOnly: true, + ), + ), + DecoratedBox( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), + child: IconButton( + onPressed: _pickContact, + icon: Icon( + SFIcons.contactsCircle, + color: Colors.white, + size: SizeUtils.getByScreen(small: 28, big: 26), + ), + ), + ), + ], + ), + SizedBox(height: SizeUtils.getByScreen(small: 14, big: 12)), + Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 24, big: 22), + vertical: SizeUtils.getByScreen(small: 10, big: 8), + ), + child: PrimaryButton( + onPressed: () async { + final vm = ref.read(contactsViewModelProvider.notifier); + final success = await vm.createContact( + name: _nameController.text, + phone: _phoneController.text, + ); + if (success && mounted) Navigator.pop(context); + }, + text: context.translate(I18n.save), + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), + ), + ], + ), ), ); } -} \ No newline at end of file + Future _pickContact() async { + final contact = await FlutterContacts.openExternalPick(); + if (contact == null || !mounted) return; + + final fullContact = await FlutterContacts.getContact( + contact.id, + withProperties: true, + ); + if (fullContact == null || fullContact.phones.isEmpty) return; + + _phoneController.text = fullContact.phones.first.number; + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/device_management/device_management_screen.dart b/modules/legacy/modules/device_management/lib/src/features/device_management/device_management_screen.dart index 63d0f55d..fe0130b2 100644 --- a/modules/legacy/modules/device_management/lib/src/features/device_management/device_management_screen.dart +++ b/modules/legacy/modules/device_management/lib/src/features/device_management/device_management_screen.dart @@ -19,117 +19,126 @@ class DeviceManagementScreen extends ConsumerWidget { return LegacyPageLayout( theme: theme, title: context.translate(I18n.functions), - body: SingleChildScrollView(child: Container( - padding: EdgeInsets.symmetric( - horizontal: SizeUtils.getByScreen(big: 22, small: 21), + showBack: false, + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(big: 22, small: 21), + ), + child: Column( + children: [ + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () => + navigationContract.pushTo(AppRoutes.remoteConnection), + icon: SFIcons.connection, + text: context.translate(I18n.remoteConnection), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () => + navigationContract.pushTo(AppRoutes.scheduledActivities), + icon: SFIcons.calendarCircle, + negativeIcon: true, + text: context.translate(I18n.calendar), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () => navigationContract.pushTo(AppRoutes.contacts), + icon: SFIcons.contactsCircle, + negativeIcon: true, + text: context.translate(I18n.contacts), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () {}, + icon: SFIcons.doNotDisturbCircle, + negativeIcon: true, + text: context.translate(I18n.doNotDisturb), + ), + // SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + // AppMenuButton( + // color: theme.getColorFor(ThemeCode.legacyPrimary), + // onPressed: () {}, + // icon: SFIcons.videoCallCircle, + // negativeIcon: true, + // text: context.translate(I18n.videoCall), + // ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () => navigationContract.pushTo(AppRoutes.health), + icon: SFIcons.healthCircle, + negativeIcon: true, + text: context.translate(I18n.health), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () => + navigationContract.pushTo(AppRoutes.activityMeter), + icon: SFIcons.healthCircle, + negativeIcon: true, + text: context.translate(I18n.activityMeter), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () => navigationContract.pushTo(AppRoutes.rewards), + icon: SFIcons.rewardsCircle, + negativeIcon: true, + text: context.translate(I18n.rewards), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () => showDialog( + context: context, + builder: (_) => Dialog(child: CallWatchDialog()), + ), + icon: Icons.call_outlined, + iconSize: SizeUtils.getByScreen(small: 42, big: 40), + text: context.translate(I18n.callWatch), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () => + navigationContract.pushTo(AppRoutes.appsUse), + icon: SFIcons.screenTime, + text: context.translate(I18n.appsUse), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () {}, + icon: Icons.app_registration_sharp, + text: context.translate(I18n.appsSurveillance), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () {}, + icon: SFIcons.friendsCircle, + negativeIcon: true, + text: context.translate(I18n.makeFriends), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: () => + navigationContract.pushTo(AppRoutes.locateDevice), + icon: SFIcons.locateSfCircle, + negativeIcon: true, + text: context.translate(I18n.locateSF), + ), + ], + ), ), - child: Column( - children: [ - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){navigationContract.pushTo(AppRoutes.remoteConnection);}, - icon: SFIcons.connection, - text: context.translate(I18n.remoteConnection) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){}, - icon: SFIcons.calendarCircle, - negativeIcon: true, - text: context.translate(I18n.calendar) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){navigationContract.pushTo(AppRoutes.contacts);}, - icon: SFIcons.contactsCircle, - negativeIcon: true, - text: context.translate(I18n.contacts) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){}, - icon: SFIcons.doNotDisturbCircle, - negativeIcon: true, - text: context.translate(I18n.doNotDisturb) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){}, - icon: SFIcons.videoCallCircle, - negativeIcon: true, - text: context.translate(I18n.videoCall) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){}, - icon: SFIcons.healthCircle, - negativeIcon: true, - text: context.translate(I18n.health) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){}, - icon: SFIcons.healthCircle, - negativeIcon: true, - text: context.translate(I18n.activityMeter) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){navigationContract.pushTo(AppRoutes.rewards);}, - icon: SFIcons.rewardsCircle, - negativeIcon: true, - text: context.translate(I18n.rewards) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){showDialog(context: context, builder: (context)=>Dialog( - child: CallWatchDialog() - ));}, - icon: Icons.call_outlined, - iconSize: SizeUtils.getByScreen(small: 42, big: 40), - text: context.translate(I18n.callWatch) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){}, - icon: SFIcons.screenTime, - text: context.translate(I18n.appsUse) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){}, - icon: Icons.app_registration_sharp, - text: context.translate(I18n.appsSurveillance) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){}, - icon: SFIcons.friendsCircle, - negativeIcon: true, - text: context.translate(I18n.makeFriends) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppMenuButton( - color: theme.getColorFor(ThemeCode.legacyPrimary), - onPressed: (){navigationContract.pushTo(AppRoutes.locateDevice);}, - icon: SFIcons.locateSfCircle, - negativeIcon: true, - text: context.translate(I18n.locateSF) - ), - ], - ), - )) + ), ); } -} \ No newline at end of file +} diff --git a/modules/legacy/modules/device_management/lib/src/features/device_management/widgets/call_watch_dialog.dart b/modules/legacy/modules/device_management/lib/src/features/device_management/widgets/call_watch_dialog.dart index e0f3425a..c2be5559 100644 --- a/modules/legacy/modules/device_management/lib/src/features/device_management/widgets/call_watch_dialog.dart +++ b/modules/legacy/modules/device_management/lib/src/features/device_management/widgets/call_watch_dialog.dart @@ -25,7 +25,7 @@ class CallWatchDialog extends ConsumerWidget { children: [ Stack( children: [ - Center(child: Text(context.translate('Call watch'), + Center(child: Text(context.translate(I18n.callWatch), textAlign: TextAlign.center, style: TextStyle(fontSize: SizeUtils.getByScreen(small: 19, big: 18)), )), @@ -41,7 +41,7 @@ class CallWatchDialog extends ConsumerWidget { SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), CustomTextField( controller: viewModel.phoneController, - hint: context.translate('Main contact phone number'), + hint: context.translate(I18n.mainContactPhoneNumber), keyboardType: TextInputType.number, ), if (viewState.errorMessage.isNotEmpty) @@ -59,7 +59,7 @@ class CallWatchDialog extends ConsumerWidget { SizedBox(height: SizeUtils.getByScreen(small: 28, big: 27)), PrimaryButton( onPressed: viewModel.call, - text: context.translate('Call me'), + text: context.translate(I18n.call), color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 38, big: 36), radius: SizeUtils.getByScreen(small: 32, big: 34), diff --git a/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/heartbeat_entity.dart b/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/heartbeat_entity.dart new file mode 100644 index 00000000..d7796064 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/heartbeat_entity.dart @@ -0,0 +1,16 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'heartbeat_entity.freezed.dart'; + +@freezed +abstract class HeartbeatEntity with _$HeartbeatEntity { + const factory HeartbeatEntity({ + required String id, + required String deviceIdentificator, + required int heartbeats, + required int? lowBloodPressure, + required int? highBloodPressure, + required int occurredAt, + required int createdAt, + }) = _HeartbeatEntity; +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/heartbeat_entity.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/heartbeat_entity.freezed.dart new file mode 100644 index 00000000..ca403f96 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/heartbeat_entity.freezed.dart @@ -0,0 +1,289 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'heartbeat_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$HeartbeatEntity { + + String get id; String get deviceIdentificator; int get heartbeats; int? get lowBloodPressure; int? get highBloodPressure; int get occurredAt; int get createdAt; +/// Create a copy of HeartbeatEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$HeartbeatEntityCopyWith get copyWith => _$HeartbeatEntityCopyWithImpl(this as HeartbeatEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is HeartbeatEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.heartbeats, heartbeats) || other.heartbeats == heartbeats)&&(identical(other.lowBloodPressure, lowBloodPressure) || other.lowBloodPressure == lowBloodPressure)&&(identical(other.highBloodPressure, highBloodPressure) || other.highBloodPressure == highBloodPressure)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,heartbeats,lowBloodPressure,highBloodPressure,occurredAt,createdAt); + +@override +String toString() { + return 'HeartbeatEntity(id: $id, deviceIdentificator: $deviceIdentificator, heartbeats: $heartbeats, lowBloodPressure: $lowBloodPressure, highBloodPressure: $highBloodPressure, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class $HeartbeatEntityCopyWith<$Res> { + factory $HeartbeatEntityCopyWith(HeartbeatEntity value, $Res Function(HeartbeatEntity) _then) = _$HeartbeatEntityCopyWithImpl; +@useResult +$Res call({ + String id, String deviceIdentificator, int heartbeats, int? lowBloodPressure, int? highBloodPressure, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class _$HeartbeatEntityCopyWithImpl<$Res> + implements $HeartbeatEntityCopyWith<$Res> { + _$HeartbeatEntityCopyWithImpl(this._self, this._then); + + final HeartbeatEntity _self; + final $Res Function(HeartbeatEntity) _then; + +/// Create a copy of HeartbeatEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceIdentificator = null,Object? heartbeats = null,Object? lowBloodPressure = freezed,Object? highBloodPressure = freezed,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,heartbeats: null == heartbeats ? _self.heartbeats : heartbeats // ignore: cast_nullable_to_non_nullable +as int,lowBloodPressure: freezed == lowBloodPressure ? _self.lowBloodPressure : lowBloodPressure // ignore: cast_nullable_to_non_nullable +as int?,highBloodPressure: freezed == highBloodPressure ? _self.highBloodPressure : highBloodPressure // ignore: cast_nullable_to_non_nullable +as int?,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [HeartbeatEntity]. +extension HeartbeatEntityPatterns on HeartbeatEntity { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _HeartbeatEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _HeartbeatEntity() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _HeartbeatEntity value) $default,){ +final _that = this; +switch (_that) { +case _HeartbeatEntity(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _HeartbeatEntity value)? $default,){ +final _that = this; +switch (_that) { +case _HeartbeatEntity() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceIdentificator, int heartbeats, int? lowBloodPressure, int? highBloodPressure, int occurredAt, int createdAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _HeartbeatEntity() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.heartbeats,_that.lowBloodPressure,_that.highBloodPressure,_that.occurredAt,_that.createdAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceIdentificator, int heartbeats, int? lowBloodPressure, int? highBloodPressure, int occurredAt, int createdAt) $default,) {final _that = this; +switch (_that) { +case _HeartbeatEntity(): +return $default(_that.id,_that.deviceIdentificator,_that.heartbeats,_that.lowBloodPressure,_that.highBloodPressure,_that.occurredAt,_that.createdAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceIdentificator, int heartbeats, int? lowBloodPressure, int? highBloodPressure, int occurredAt, int createdAt)? $default,) {final _that = this; +switch (_that) { +case _HeartbeatEntity() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.heartbeats,_that.lowBloodPressure,_that.highBloodPressure,_that.occurredAt,_that.createdAt);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _HeartbeatEntity implements HeartbeatEntity { + const _HeartbeatEntity({required this.id, required this.deviceIdentificator, required this.heartbeats, required this.lowBloodPressure, required this.highBloodPressure, required this.occurredAt, required this.createdAt}); + + +@override final String id; +@override final String deviceIdentificator; +@override final int heartbeats; +@override final int? lowBloodPressure; +@override final int? highBloodPressure; +@override final int occurredAt; +@override final int createdAt; + +/// Create a copy of HeartbeatEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$HeartbeatEntityCopyWith<_HeartbeatEntity> get copyWith => __$HeartbeatEntityCopyWithImpl<_HeartbeatEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _HeartbeatEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.heartbeats, heartbeats) || other.heartbeats == heartbeats)&&(identical(other.lowBloodPressure, lowBloodPressure) || other.lowBloodPressure == lowBloodPressure)&&(identical(other.highBloodPressure, highBloodPressure) || other.highBloodPressure == highBloodPressure)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,heartbeats,lowBloodPressure,highBloodPressure,occurredAt,createdAt); + +@override +String toString() { + return 'HeartbeatEntity(id: $id, deviceIdentificator: $deviceIdentificator, heartbeats: $heartbeats, lowBloodPressure: $lowBloodPressure, highBloodPressure: $highBloodPressure, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$HeartbeatEntityCopyWith<$Res> implements $HeartbeatEntityCopyWith<$Res> { + factory _$HeartbeatEntityCopyWith(_HeartbeatEntity value, $Res Function(_HeartbeatEntity) _then) = __$HeartbeatEntityCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceIdentificator, int heartbeats, int? lowBloodPressure, int? highBloodPressure, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class __$HeartbeatEntityCopyWithImpl<$Res> + implements _$HeartbeatEntityCopyWith<$Res> { + __$HeartbeatEntityCopyWithImpl(this._self, this._then); + + final _HeartbeatEntity _self; + final $Res Function(_HeartbeatEntity) _then; + +/// Create a copy of HeartbeatEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceIdentificator = null,Object? heartbeats = null,Object? lowBloodPressure = freezed,Object? highBloodPressure = freezed,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_HeartbeatEntity( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,heartbeats: null == heartbeats ? _self.heartbeats : heartbeats // ignore: cast_nullable_to_non_nullable +as int,lowBloodPressure: freezed == lowBloodPressure ? _self.lowBloodPressure : lowBloodPressure // ignore: cast_nullable_to_non_nullable +as int?,highBloodPressure: freezed == highBloodPressure ? _self.highBloodPressure : highBloodPressure // ignore: cast_nullable_to_non_nullable +as int?,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/oxygen_entity.dart b/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/oxygen_entity.dart new file mode 100644 index 00000000..b95615e0 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/oxygen_entity.dart @@ -0,0 +1,14 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'oxygen_entity.freezed.dart'; + +@freezed +abstract class OxygenEntity with _$OxygenEntity { + const factory OxygenEntity({ + required String id, + required String deviceIdentificator, + required int oxygen, + required int occurredAt, + required int createdAt, + }) = _OxygenEntity; +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/oxygen_entity.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/oxygen_entity.freezed.dart new file mode 100644 index 00000000..1aecc529 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/domain/entities/oxygen_entity.freezed.dart @@ -0,0 +1,283 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'oxygen_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$OxygenEntity { + + String get id; String get deviceIdentificator; int get oxygen; int get occurredAt; int get createdAt; +/// Create a copy of OxygenEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$OxygenEntityCopyWith get copyWith => _$OxygenEntityCopyWithImpl(this as OxygenEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is OxygenEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.oxygen, oxygen) || other.oxygen == oxygen)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,oxygen,occurredAt,createdAt); + +@override +String toString() { + return 'OxygenEntity(id: $id, deviceIdentificator: $deviceIdentificator, oxygen: $oxygen, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class $OxygenEntityCopyWith<$Res> { + factory $OxygenEntityCopyWith(OxygenEntity value, $Res Function(OxygenEntity) _then) = _$OxygenEntityCopyWithImpl; +@useResult +$Res call({ + String id, String deviceIdentificator, int oxygen, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class _$OxygenEntityCopyWithImpl<$Res> + implements $OxygenEntityCopyWith<$Res> { + _$OxygenEntityCopyWithImpl(this._self, this._then); + + final OxygenEntity _self; + final $Res Function(OxygenEntity) _then; + +/// Create a copy of OxygenEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceIdentificator = null,Object? oxygen = null,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,oxygen: null == oxygen ? _self.oxygen : oxygen // ignore: cast_nullable_to_non_nullable +as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [OxygenEntity]. +extension OxygenEntityPatterns on OxygenEntity { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _OxygenEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _OxygenEntity() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _OxygenEntity value) $default,){ +final _that = this; +switch (_that) { +case _OxygenEntity(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _OxygenEntity value)? $default,){ +final _that = this; +switch (_that) { +case _OxygenEntity() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceIdentificator, int oxygen, int occurredAt, int createdAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _OxygenEntity() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.oxygen,_that.occurredAt,_that.createdAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceIdentificator, int oxygen, int occurredAt, int createdAt) $default,) {final _that = this; +switch (_that) { +case _OxygenEntity(): +return $default(_that.id,_that.deviceIdentificator,_that.oxygen,_that.occurredAt,_that.createdAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceIdentificator, int oxygen, int occurredAt, int createdAt)? $default,) {final _that = this; +switch (_that) { +case _OxygenEntity() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.oxygen,_that.occurredAt,_that.createdAt);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _OxygenEntity implements OxygenEntity { + const _OxygenEntity({required this.id, required this.deviceIdentificator, required this.oxygen, required this.occurredAt, required this.createdAt}); + + +@override final String id; +@override final String deviceIdentificator; +@override final int oxygen; +@override final int occurredAt; +@override final int createdAt; + +/// Create a copy of OxygenEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$OxygenEntityCopyWith<_OxygenEntity> get copyWith => __$OxygenEntityCopyWithImpl<_OxygenEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _OxygenEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.oxygen, oxygen) || other.oxygen == oxygen)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,oxygen,occurredAt,createdAt); + +@override +String toString() { + return 'OxygenEntity(id: $id, deviceIdentificator: $deviceIdentificator, oxygen: $oxygen, occurredAt: $occurredAt, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$OxygenEntityCopyWith<$Res> implements $OxygenEntityCopyWith<$Res> { + factory _$OxygenEntityCopyWith(_OxygenEntity value, $Res Function(_OxygenEntity) _then) = __$OxygenEntityCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceIdentificator, int oxygen, int occurredAt, int createdAt +}); + + + + +} +/// @nodoc +class __$OxygenEntityCopyWithImpl<$Res> + implements _$OxygenEntityCopyWith<$Res> { + __$OxygenEntityCopyWithImpl(this._self, this._then); + + final _OxygenEntity _self; + final $Res Function(_OxygenEntity) _then; + +/// Create a copy of OxygenEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceIdentificator = null,Object? oxygen = null,Object? occurredAt = null,Object? createdAt = null,}) { + return _then(_OxygenEntity( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,oxygen: null == oxygen ? _self.oxygen : oxygen // ignore: cast_nullable_to_non_nullable +as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/features/health/health_builder.dart b/modules/legacy/modules/device_management/lib/src/features/health/health_builder.dart new file mode 100644 index 00000000..8132ad4b --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/health_builder.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:go_router/go_router.dart'; +import 'package:navigation/navigation.dart'; + +import 'presentation/health_screen.dart'; + +class HealthBuilder { + const HealthBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: HealthScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/health_colors.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/health_colors.dart new file mode 100644 index 00000000..b2c341d0 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/health_colors.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; + +const _kGreen = Color(0xFF4CAF50); +const _kOrange = Color(0xFFFF9800); +const _kRed = Color(0xFFFF5D52); + +Color heartRateColor(int bpm) { + if (bpm < 50 || bpm > 120) return _kRed; + if (bpm < 60 || bpm > 100) return _kOrange; + return _kGreen; +} + +Color systolicColor(int systolic) { + if (systolic >= 140) return _kRed; + if (systolic >= 120) return _kOrange; + return _kGreen; +} + +Color diastolicColor(int diastolic) { + if (diastolic >= 90) return _kRed; + if (diastolic >= 80) return _kOrange; + return _kGreen; +} + +Color bloodPressureColor(int systolic, int diastolic) { + final sys = systolicColor(systolic); + final dia = diastolicColor(diastolic); + if (sys == _kRed || dia == _kRed) return _kRed; + if (sys == _kOrange || dia == _kOrange) return _kOrange; + return _kGreen; +} + +Color oxygenColor(int spo2) { + if (spo2 < 90) return _kRed; + if (spo2 < 95) return _kOrange; + return _kGreen; +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/health_screen.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/health_screen.dart new file mode 100644 index 00000000..1d60dd31 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/health_screen.dart @@ -0,0 +1,135 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:navigation/navigation.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import 'state/health_view_model.dart'; +import 'widgets/blood_pressure_tab.dart'; +import 'widgets/health_summary_cards.dart'; +import 'widgets/heart_rate_tab.dart'; +import 'widgets/oxygen_tab.dart'; +import '../../../core/presentation/widgets/time_range_selector.dart'; + +class HealthScreen extends ConsumerStatefulWidget { + final NavigationContract navigationContract; + + const HealthScreen({super.key, required this.navigationContract}); + + @override + ConsumerState createState() => _HealthScreenState(); +} + +class _HealthScreenState extends ConsumerState + with SingleTickerProviderStateMixin { + late final TabController _tabController; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 3, vsync: this); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + Future _pickCustomRange(HealthViewModel vm) async { + final now = DateTime.now(); + final picked = await showDateRangePicker( + context: context, + firstDate: now.subtract(const Duration(days: 365)), + lastDate: now, + ); + if (picked != null) { + vm.selectCustomRange(picked.start, picked.end); + } + } + + @override + Widget build(BuildContext context) { + final theme = ref.watch(themePortProvider); + final state = ref.watch(healthViewModelProvider); + final vm = ref.read(healthViewModelProvider.notifier); + + ref.listen( + healthViewModelProvider.select((s) => s.errorMessage), + (previous, next) { + if (next.isNotEmpty) { + showTopSnackbar(context, message: next, type: MessageType.error); + } + }, + ); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.health), + body: state.isLoading + ? const Center(child: CircularProgressIndicator()) + : Column( + children: [ + HealthSummaryCards( + heartbeats: state.latestHeartbeats, + oxygens: state.latestOxygens, + tabController: _tabController, + theme: theme, + ), + TimeRangeSelector( + selected: state.timeRange, + onSelected: (range) => vm.selectTimeRange(range), + onCustomTap: () => _pickCustomRange(vm), + theme: theme, + ), + TabBar( + controller: _tabController, + labelColor: theme.getColorFor(ThemeCode.legacyPrimary), + unselectedLabelColor: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + indicatorColor: theme.getColorFor(ThemeCode.legacyPrimary), + labelStyle: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + fontWeight: FontWeight.w600, + ), + tabs: [ + Tab(text: context.translate(I18n.heartRate)), + Tab(text: context.translate(I18n.bloodPressure)), + Tab(text: context.translate(I18n.oxygenLevel)), + ], + ), + Expanded( + child: TabBarView( + controller: _tabController, + children: [ + HeartRateTab( + chartData: state.chartHeartbeats, + historyData: state.historyHeartbeats, + stats: state.heartRateStats, + hasMore: state.hasMoreHistory, + isLoadingMore: state.isLoadingMore, + ), + BloodPressureTab( + chartData: state.chartHeartbeats, + historyData: state.historyHeartbeats, + hasMore: state.hasMoreHistory, + isLoadingMore: state.isLoadingMore, + ), + OxygenTab( + chartData: state.chartOxygens, + historyData: state.historyOxygens, + stats: state.oxygenStats, + hasMore: state.hasMoreHistory, + isLoadingMore: state.isLoadingMore, + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_model.dart new file mode 100644 index 00000000..5cf4a7dd --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_model.dart @@ -0,0 +1,246 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; + +import '../../../../core/data/datasources/health_query_builder.dart'; +import '../../../../core/presentation/time_range.dart'; +import '../../../../core/domain/repositories/health_repository.dart'; +import '../../../../core/providers/health_repository_provider.dart'; +import 'health_view_state.dart'; + +final healthViewModelProvider = + NotifierProvider.autoDispose( + HealthViewModel.new, +); + +class HealthViewModel extends Notifier { + late final HealthRepository _repository; + + static const int _historyPageSize = 20; + + @override + HealthViewState build() { + _repository = ref.read(healthRepositoryProvider); + _init(); + return const HealthViewState(); + } + + String? get _identificator => + ref.read(selectedDeviceProvider)?.identificator; + + + Future selectTimeRange(TimeRange range) async { + if (range == state.timeRange) return; + state = state.copyWith(timeRange: range, isLoading: true); + await _loadFilteredData(); + } + + Future selectCustomRange(DateTime start, DateTime end) async { + state = state.copyWith( + timeRange: TimeRange.custom, + customStart: start, + customEnd: end, + isLoading: true, + ); + await _loadFilteredData(); + } + + Future loadMoreHistory() async { + if (state.isLoadingMore || !state.hasMoreHistory) return; + final identificator = _identificator; + if (identificator == null) return; + + state = state.copyWith(isLoadingMore: true); + + try { + final nextPage = state.currentHistoryPage + 1; + final filters = _buildTimeFilters(); + + final (heartbeats, oxygens) = await ( + _repository.getHeartbeats( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + page: nextPage, + pageSize: _historyPageSize, + filters: filters, + ), + ), + _repository.getOxygens( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + page: nextPage, + pageSize: _historyPageSize, + filters: filters, + ), + ), + ).wait; + if (!ref.mounted) return; + + state = state.copyWith( + historyHeartbeats: [...state.historyHeartbeats, ...heartbeats], + historyOxygens: [...state.historyOxygens, ...oxygens], + currentHistoryPage: nextPage, + hasMoreHistory: heartbeats.length >= _historyPageSize || + oxygens.length >= _historyPageSize, + isLoadingMore: false, + ); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith( + isLoadingMore: false, + errorMessage: _formatError(e), + ); + } + } + + + Future _init() async { + final identificator = _identificator; + if (identificator == null) { + state = state.copyWith(isLoading: false); + return; + } + + try { + final (latestHeartbeats, latestOxygens) = await ( + _repository.getHeartbeats( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + pageSize: 5, + ), + ), + _repository.getOxygens( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + pageSize: 5, + ), + ), + ).wait; + if (!ref.mounted) return; + + state = state.copyWith( + latestHeartbeats: latestHeartbeats, + latestOxygens: latestOxygens, + ); + + await _loadFilteredData(); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } + } + + Future _loadFilteredData() async { + final identificator = _identificator; + if (identificator == null) { + state = state.copyWith(isLoading: false); + return; + } + + try { + final filters = _buildTimeFilters(); + + final (chartHeartbeats, chartOxygens, histHeartbeats, histOxygens) = + await ( + _repository.getHeartbeats( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.asc, + filters: filters, + ), + ), + _repository.getOxygens( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.asc, + filters: filters, + ), + ), + _repository.getHeartbeats( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + page: 1, + pageSize: _historyPageSize, + filters: filters, + ), + ), + _repository.getOxygens( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + page: 1, + pageSize: _historyPageSize, + filters: filters, + ), + ), + ).wait; + if (!ref.mounted) return; + + state = state.copyWith( + chartHeartbeats: chartHeartbeats, + chartOxygens: chartOxygens, + historyHeartbeats: histHeartbeats, + historyOxygens: histOxygens, + currentHistoryPage: 1, + hasMoreHistory: histHeartbeats.length >= _historyPageSize || + histOxygens.length >= _historyPageSize, + heartRateStats: _computeStats( + chartHeartbeats.map((e) => e.heartbeats).toList(), + ), + oxygenStats: _computeStats( + chartOxygens.map((e) => e.oxygen).toList(), + ), + isLoading: false, + errorMessage: '', + ); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } + } + + List? _buildTimeFilters() { + final range = _getTimeRange(); + if (range == null) return null; + + final (start, end) = range; + return HealthQueryBuilder.timeRangeFilters(start: start, end: end); + } + + (DateTime, DateTime)? _getTimeRange() { + final now = DateTime.now(); + final todayStart = DateTime(now.year, now.month, now.day); + + switch (state.timeRange) { + case TimeRange.today: + return (todayStart, now); + case TimeRange.sevenDays: + return (todayStart.subtract(const Duration(days: 6)), now); + case TimeRange.thirtyDays: + return (todayStart.subtract(const Duration(days: 29)), now); + case TimeRange.custom: + if (state.customStart != null && state.customEnd != null) { + return (state.customStart!, state.customEnd!); + } + return null; + } + } + + HealthStats _computeStats(List values) { + if (values.isEmpty) return const HealthStats(); + return HealthStats( + avg: (values.reduce((a, b) => a + b) / values.length).round(), + min: values.reduce((a, b) => a < b ? a : b), + max: values.reduce((a, b) => a > b ? a : b), + ); + } + + String _formatError(Object e) { + final msg = e.toString(); + return msg.startsWith('Exception: ') ? msg.substring(11) : msg; + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_state.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_state.dart new file mode 100644 index 00000000..c186fa52 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_state.dart @@ -0,0 +1,38 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../../../core/presentation/time_range.dart'; +import '../../domain/entities/heartbeat_entity.dart'; +import '../../domain/entities/oxygen_entity.dart'; + +part 'health_view_state.freezed.dart'; + +@freezed +abstract class HealthStats with _$HealthStats { + const factory HealthStats({ + @Default(0) int avg, + @Default(0) int min, + @Default(0) int max, + }) = _HealthStats; +} + +@freezed +abstract class HealthViewState with _$HealthViewState { + const factory HealthViewState({ + @Default([]) List latestHeartbeats, + @Default([]) List latestOxygens, + @Default([]) List chartHeartbeats, + @Default([]) List chartOxygens, + @Default([]) List historyHeartbeats, + @Default([]) List historyOxygens, + @Default(1) int currentHistoryPage, + @Default(false) bool hasMoreHistory, + @Default(HealthStats()) HealthStats heartRateStats, + @Default(HealthStats()) HealthStats oxygenStats, + @Default(TimeRange.today) TimeRange timeRange, + @Default(null) DateTime? customStart, + @Default(null) DateTime? customEnd, + @Default(true) bool isLoading, + @Default(false) bool isLoadingMore, + @Default('') String errorMessage, + }) = _HealthViewState; +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_state.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_state.freezed.dart new file mode 100644 index 00000000..e8798e1e --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/state/health_view_state.freezed.dart @@ -0,0 +1,651 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'health_view_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$HealthStats { + + int get avg; int get min; int get max; +/// Create a copy of HealthStats +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$HealthStatsCopyWith get copyWith => _$HealthStatsCopyWithImpl(this as HealthStats, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is HealthStats&&(identical(other.avg, avg) || other.avg == avg)&&(identical(other.min, min) || other.min == min)&&(identical(other.max, max) || other.max == max)); +} + + +@override +int get hashCode => Object.hash(runtimeType,avg,min,max); + +@override +String toString() { + return 'HealthStats(avg: $avg, min: $min, max: $max)'; +} + + +} + +/// @nodoc +abstract mixin class $HealthStatsCopyWith<$Res> { + factory $HealthStatsCopyWith(HealthStats value, $Res Function(HealthStats) _then) = _$HealthStatsCopyWithImpl; +@useResult +$Res call({ + int avg, int min, int max +}); + + + + +} +/// @nodoc +class _$HealthStatsCopyWithImpl<$Res> + implements $HealthStatsCopyWith<$Res> { + _$HealthStatsCopyWithImpl(this._self, this._then); + + final HealthStats _self; + final $Res Function(HealthStats) _then; + +/// Create a copy of HealthStats +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? avg = null,Object? min = null,Object? max = null,}) { + return _then(_self.copyWith( +avg: null == avg ? _self.avg : avg // ignore: cast_nullable_to_non_nullable +as int,min: null == min ? _self.min : min // ignore: cast_nullable_to_non_nullable +as int,max: null == max ? _self.max : max // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [HealthStats]. +extension HealthStatsPatterns on HealthStats { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _HealthStats value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _HealthStats() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _HealthStats value) $default,){ +final _that = this; +switch (_that) { +case _HealthStats(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _HealthStats value)? $default,){ +final _that = this; +switch (_that) { +case _HealthStats() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int avg, int min, int max)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _HealthStats() when $default != null: +return $default(_that.avg,_that.min,_that.max);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int avg, int min, int max) $default,) {final _that = this; +switch (_that) { +case _HealthStats(): +return $default(_that.avg,_that.min,_that.max);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int avg, int min, int max)? $default,) {final _that = this; +switch (_that) { +case _HealthStats() when $default != null: +return $default(_that.avg,_that.min,_that.max);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _HealthStats implements HealthStats { + const _HealthStats({this.avg = 0, this.min = 0, this.max = 0}); + + +@override@JsonKey() final int avg; +@override@JsonKey() final int min; +@override@JsonKey() final int max; + +/// Create a copy of HealthStats +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$HealthStatsCopyWith<_HealthStats> get copyWith => __$HealthStatsCopyWithImpl<_HealthStats>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _HealthStats&&(identical(other.avg, avg) || other.avg == avg)&&(identical(other.min, min) || other.min == min)&&(identical(other.max, max) || other.max == max)); +} + + +@override +int get hashCode => Object.hash(runtimeType,avg,min,max); + +@override +String toString() { + return 'HealthStats(avg: $avg, min: $min, max: $max)'; +} + + +} + +/// @nodoc +abstract mixin class _$HealthStatsCopyWith<$Res> implements $HealthStatsCopyWith<$Res> { + factory _$HealthStatsCopyWith(_HealthStats value, $Res Function(_HealthStats) _then) = __$HealthStatsCopyWithImpl; +@override @useResult +$Res call({ + int avg, int min, int max +}); + + + + +} +/// @nodoc +class __$HealthStatsCopyWithImpl<$Res> + implements _$HealthStatsCopyWith<$Res> { + __$HealthStatsCopyWithImpl(this._self, this._then); + + final _HealthStats _self; + final $Res Function(_HealthStats) _then; + +/// Create a copy of HealthStats +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? avg = null,Object? min = null,Object? max = null,}) { + return _then(_HealthStats( +avg: null == avg ? _self.avg : avg // ignore: cast_nullable_to_non_nullable +as int,min: null == min ? _self.min : min // ignore: cast_nullable_to_non_nullable +as int,max: null == max ? _self.max : max // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +/// @nodoc +mixin _$HealthViewState { + + List get latestHeartbeats; List get latestOxygens; List get chartHeartbeats; List get chartOxygens; List get historyHeartbeats; List get historyOxygens; int get currentHistoryPage; bool get hasMoreHistory; HealthStats get heartRateStats; HealthStats get oxygenStats; TimeRange get timeRange; DateTime? get customStart; DateTime? get customEnd; bool get isLoading; bool get isLoadingMore; String get errorMessage; +/// Create a copy of HealthViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$HealthViewStateCopyWith get copyWith => _$HealthViewStateCopyWithImpl(this as HealthViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is HealthViewState&&const DeepCollectionEquality().equals(other.latestHeartbeats, latestHeartbeats)&&const DeepCollectionEquality().equals(other.latestOxygens, latestOxygens)&&const DeepCollectionEquality().equals(other.chartHeartbeats, chartHeartbeats)&&const DeepCollectionEquality().equals(other.chartOxygens, chartOxygens)&&const DeepCollectionEquality().equals(other.historyHeartbeats, historyHeartbeats)&&const DeepCollectionEquality().equals(other.historyOxygens, historyOxygens)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.heartRateStats, heartRateStats) || other.heartRateStats == heartRateStats)&&(identical(other.oxygenStats, oxygenStats) || other.oxygenStats == oxygenStats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(latestHeartbeats),const DeepCollectionEquality().hash(latestOxygens),const DeepCollectionEquality().hash(chartHeartbeats),const DeepCollectionEquality().hash(chartOxygens),const DeepCollectionEquality().hash(historyHeartbeats),const DeepCollectionEquality().hash(historyOxygens),currentHistoryPage,hasMoreHistory,heartRateStats,oxygenStats,timeRange,customStart,customEnd,isLoading,isLoadingMore,errorMessage); + +@override +String toString() { + return 'HealthViewState(latestHeartbeats: $latestHeartbeats, latestOxygens: $latestOxygens, chartHeartbeats: $chartHeartbeats, chartOxygens: $chartOxygens, historyHeartbeats: $historyHeartbeats, historyOxygens: $historyOxygens, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, heartRateStats: $heartRateStats, oxygenStats: $oxygenStats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class $HealthViewStateCopyWith<$Res> { + factory $HealthViewStateCopyWith(HealthViewState value, $Res Function(HealthViewState) _then) = _$HealthViewStateCopyWithImpl; +@useResult +$Res call({ + List latestHeartbeats, List latestOxygens, List chartHeartbeats, List chartOxygens, List historyHeartbeats, List historyOxygens, int currentHistoryPage, bool hasMoreHistory, HealthStats heartRateStats, HealthStats oxygenStats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage +}); + + +$HealthStatsCopyWith<$Res> get heartRateStats;$HealthStatsCopyWith<$Res> get oxygenStats; + +} +/// @nodoc +class _$HealthViewStateCopyWithImpl<$Res> + implements $HealthViewStateCopyWith<$Res> { + _$HealthViewStateCopyWithImpl(this._self, this._then); + + final HealthViewState _self; + final $Res Function(HealthViewState) _then; + +/// Create a copy of HealthViewState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? latestHeartbeats = null,Object? latestOxygens = null,Object? chartHeartbeats = null,Object? chartOxygens = null,Object? historyHeartbeats = null,Object? historyOxygens = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? heartRateStats = null,Object? oxygenStats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorMessage = null,}) { + return _then(_self.copyWith( +latestHeartbeats: null == latestHeartbeats ? _self.latestHeartbeats : latestHeartbeats // ignore: cast_nullable_to_non_nullable +as List,latestOxygens: null == latestOxygens ? _self.latestOxygens : latestOxygens // ignore: cast_nullable_to_non_nullable +as List,chartHeartbeats: null == chartHeartbeats ? _self.chartHeartbeats : chartHeartbeats // ignore: cast_nullable_to_non_nullable +as List,chartOxygens: null == chartOxygens ? _self.chartOxygens : chartOxygens // ignore: cast_nullable_to_non_nullable +as List,historyHeartbeats: null == historyHeartbeats ? _self.historyHeartbeats : historyHeartbeats // ignore: cast_nullable_to_non_nullable +as List,historyOxygens: null == historyOxygens ? _self.historyOxygens : historyOxygens // ignore: cast_nullable_to_non_nullable +as List,currentHistoryPage: null == currentHistoryPage ? _self.currentHistoryPage : currentHistoryPage // ignore: cast_nullable_to_non_nullable +as int,hasMoreHistory: null == hasMoreHistory ? _self.hasMoreHistory : hasMoreHistory // ignore: cast_nullable_to_non_nullable +as bool,heartRateStats: null == heartRateStats ? _self.heartRateStats : heartRateStats // ignore: cast_nullable_to_non_nullable +as HealthStats,oxygenStats: null == oxygenStats ? _self.oxygenStats : oxygenStats // ignore: cast_nullable_to_non_nullable +as HealthStats,timeRange: null == timeRange ? _self.timeRange : timeRange // ignore: cast_nullable_to_non_nullable +as TimeRange,customStart: freezed == customStart ? _self.customStart : customStart // ignore: cast_nullable_to_non_nullable +as DateTime?,customEnd: freezed == customEnd ? _self.customEnd : customEnd // ignore: cast_nullable_to_non_nullable +as DateTime?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} +/// Create a copy of HealthViewState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$HealthStatsCopyWith<$Res> get heartRateStats { + + return $HealthStatsCopyWith<$Res>(_self.heartRateStats, (value) { + return _then(_self.copyWith(heartRateStats: value)); + }); +}/// Create a copy of HealthViewState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$HealthStatsCopyWith<$Res> get oxygenStats { + + return $HealthStatsCopyWith<$Res>(_self.oxygenStats, (value) { + return _then(_self.copyWith(oxygenStats: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [HealthViewState]. +extension HealthViewStatePatterns on HealthViewState { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _HealthViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _HealthViewState() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _HealthViewState value) $default,){ +final _that = this; +switch (_that) { +case _HealthViewState(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _HealthViewState value)? $default,){ +final _that = this; +switch (_that) { +case _HealthViewState() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( List latestHeartbeats, List latestOxygens, List chartHeartbeats, List chartOxygens, List historyHeartbeats, List historyOxygens, int currentHistoryPage, bool hasMoreHistory, HealthStats heartRateStats, HealthStats oxygenStats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _HealthViewState() when $default != null: +return $default(_that.latestHeartbeats,_that.latestOxygens,_that.chartHeartbeats,_that.chartOxygens,_that.historyHeartbeats,_that.historyOxygens,_that.currentHistoryPage,_that.hasMoreHistory,_that.heartRateStats,_that.oxygenStats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( List latestHeartbeats, List latestOxygens, List chartHeartbeats, List chartOxygens, List historyHeartbeats, List historyOxygens, int currentHistoryPage, bool hasMoreHistory, HealthStats heartRateStats, HealthStats oxygenStats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage) $default,) {final _that = this; +switch (_that) { +case _HealthViewState(): +return $default(_that.latestHeartbeats,_that.latestOxygens,_that.chartHeartbeats,_that.chartOxygens,_that.historyHeartbeats,_that.historyOxygens,_that.currentHistoryPage,_that.hasMoreHistory,_that.heartRateStats,_that.oxygenStats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List latestHeartbeats, List latestOxygens, List chartHeartbeats, List chartOxygens, List historyHeartbeats, List historyOxygens, int currentHistoryPage, bool hasMoreHistory, HealthStats heartRateStats, HealthStats oxygenStats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage)? $default,) {final _that = this; +switch (_that) { +case _HealthViewState() when $default != null: +return $default(_that.latestHeartbeats,_that.latestOxygens,_that.chartHeartbeats,_that.chartOxygens,_that.historyHeartbeats,_that.historyOxygens,_that.currentHistoryPage,_that.hasMoreHistory,_that.heartRateStats,_that.oxygenStats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _HealthViewState implements HealthViewState { + const _HealthViewState({final List latestHeartbeats = const [], final List latestOxygens = const [], final List chartHeartbeats = const [], final List chartOxygens = const [], final List historyHeartbeats = const [], final List historyOxygens = const [], this.currentHistoryPage = 1, this.hasMoreHistory = false, this.heartRateStats = const HealthStats(), this.oxygenStats = const HealthStats(), this.timeRange = TimeRange.today, this.customStart = null, this.customEnd = null, this.isLoading = true, this.isLoadingMore = false, this.errorMessage = ''}): _latestHeartbeats = latestHeartbeats,_latestOxygens = latestOxygens,_chartHeartbeats = chartHeartbeats,_chartOxygens = chartOxygens,_historyHeartbeats = historyHeartbeats,_historyOxygens = historyOxygens; + + + final List _latestHeartbeats; +@override@JsonKey() List get latestHeartbeats { + if (_latestHeartbeats is EqualUnmodifiableListView) return _latestHeartbeats; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_latestHeartbeats); +} + + final List _latestOxygens; +@override@JsonKey() List get latestOxygens { + if (_latestOxygens is EqualUnmodifiableListView) return _latestOxygens; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_latestOxygens); +} + + final List _chartHeartbeats; +@override@JsonKey() List get chartHeartbeats { + if (_chartHeartbeats is EqualUnmodifiableListView) return _chartHeartbeats; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_chartHeartbeats); +} + + final List _chartOxygens; +@override@JsonKey() List get chartOxygens { + if (_chartOxygens is EqualUnmodifiableListView) return _chartOxygens; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_chartOxygens); +} + + final List _historyHeartbeats; +@override@JsonKey() List get historyHeartbeats { + if (_historyHeartbeats is EqualUnmodifiableListView) return _historyHeartbeats; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_historyHeartbeats); +} + + final List _historyOxygens; +@override@JsonKey() List get historyOxygens { + if (_historyOxygens is EqualUnmodifiableListView) return _historyOxygens; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_historyOxygens); +} + +@override@JsonKey() final int currentHistoryPage; +@override@JsonKey() final bool hasMoreHistory; +@override@JsonKey() final HealthStats heartRateStats; +@override@JsonKey() final HealthStats oxygenStats; +@override@JsonKey() final TimeRange timeRange; +@override@JsonKey() final DateTime? customStart; +@override@JsonKey() final DateTime? customEnd; +@override@JsonKey() final bool isLoading; +@override@JsonKey() final bool isLoadingMore; +@override@JsonKey() final String errorMessage; + +/// Create a copy of HealthViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$HealthViewStateCopyWith<_HealthViewState> get copyWith => __$HealthViewStateCopyWithImpl<_HealthViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _HealthViewState&&const DeepCollectionEquality().equals(other._latestHeartbeats, _latestHeartbeats)&&const DeepCollectionEquality().equals(other._latestOxygens, _latestOxygens)&&const DeepCollectionEquality().equals(other._chartHeartbeats, _chartHeartbeats)&&const DeepCollectionEquality().equals(other._chartOxygens, _chartOxygens)&&const DeepCollectionEquality().equals(other._historyHeartbeats, _historyHeartbeats)&&const DeepCollectionEquality().equals(other._historyOxygens, _historyOxygens)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.heartRateStats, heartRateStats) || other.heartRateStats == heartRateStats)&&(identical(other.oxygenStats, oxygenStats) || other.oxygenStats == oxygenStats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_latestHeartbeats),const DeepCollectionEquality().hash(_latestOxygens),const DeepCollectionEquality().hash(_chartHeartbeats),const DeepCollectionEquality().hash(_chartOxygens),const DeepCollectionEquality().hash(_historyHeartbeats),const DeepCollectionEquality().hash(_historyOxygens),currentHistoryPage,hasMoreHistory,heartRateStats,oxygenStats,timeRange,customStart,customEnd,isLoading,isLoadingMore,errorMessage); + +@override +String toString() { + return 'HealthViewState(latestHeartbeats: $latestHeartbeats, latestOxygens: $latestOxygens, chartHeartbeats: $chartHeartbeats, chartOxygens: $chartOxygens, historyHeartbeats: $historyHeartbeats, historyOxygens: $historyOxygens, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, heartRateStats: $heartRateStats, oxygenStats: $oxygenStats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class _$HealthViewStateCopyWith<$Res> implements $HealthViewStateCopyWith<$Res> { + factory _$HealthViewStateCopyWith(_HealthViewState value, $Res Function(_HealthViewState) _then) = __$HealthViewStateCopyWithImpl; +@override @useResult +$Res call({ + List latestHeartbeats, List latestOxygens, List chartHeartbeats, List chartOxygens, List historyHeartbeats, List historyOxygens, int currentHistoryPage, bool hasMoreHistory, HealthStats heartRateStats, HealthStats oxygenStats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage +}); + + +@override $HealthStatsCopyWith<$Res> get heartRateStats;@override $HealthStatsCopyWith<$Res> get oxygenStats; + +} +/// @nodoc +class __$HealthViewStateCopyWithImpl<$Res> + implements _$HealthViewStateCopyWith<$Res> { + __$HealthViewStateCopyWithImpl(this._self, this._then); + + final _HealthViewState _self; + final $Res Function(_HealthViewState) _then; + +/// Create a copy of HealthViewState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? latestHeartbeats = null,Object? latestOxygens = null,Object? chartHeartbeats = null,Object? chartOxygens = null,Object? historyHeartbeats = null,Object? historyOxygens = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? heartRateStats = null,Object? oxygenStats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorMessage = null,}) { + return _then(_HealthViewState( +latestHeartbeats: null == latestHeartbeats ? _self._latestHeartbeats : latestHeartbeats // ignore: cast_nullable_to_non_nullable +as List,latestOxygens: null == latestOxygens ? _self._latestOxygens : latestOxygens // ignore: cast_nullable_to_non_nullable +as List,chartHeartbeats: null == chartHeartbeats ? _self._chartHeartbeats : chartHeartbeats // ignore: cast_nullable_to_non_nullable +as List,chartOxygens: null == chartOxygens ? _self._chartOxygens : chartOxygens // ignore: cast_nullable_to_non_nullable +as List,historyHeartbeats: null == historyHeartbeats ? _self._historyHeartbeats : historyHeartbeats // ignore: cast_nullable_to_non_nullable +as List,historyOxygens: null == historyOxygens ? _self._historyOxygens : historyOxygens // ignore: cast_nullable_to_non_nullable +as List,currentHistoryPage: null == currentHistoryPage ? _self.currentHistoryPage : currentHistoryPage // ignore: cast_nullable_to_non_nullable +as int,hasMoreHistory: null == hasMoreHistory ? _self.hasMoreHistory : hasMoreHistory // ignore: cast_nullable_to_non_nullable +as bool,heartRateStats: null == heartRateStats ? _self.heartRateStats : heartRateStats // ignore: cast_nullable_to_non_nullable +as HealthStats,oxygenStats: null == oxygenStats ? _self.oxygenStats : oxygenStats // ignore: cast_nullable_to_non_nullable +as HealthStats,timeRange: null == timeRange ? _self.timeRange : timeRange // ignore: cast_nullable_to_non_nullable +as TimeRange,customStart: freezed == customStart ? _self.customStart : customStart // ignore: cast_nullable_to_non_nullable +as DateTime?,customEnd: freezed == customEnd ? _self.customEnd : customEnd // ignore: cast_nullable_to_non_nullable +as DateTime?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +/// Create a copy of HealthViewState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$HealthStatsCopyWith<$Res> get heartRateStats { + + return $HealthStatsCopyWith<$Res>(_self.heartRateStats, (value) { + return _then(_self.copyWith(heartRateStats: value)); + }); +}/// Create a copy of HealthViewState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$HealthStatsCopyWith<$Res> get oxygenStats { + + return $HealthStatsCopyWith<$Res>(_self.oxygenStats, (value) { + return _then(_self.copyWith(oxygenStats: value)); + }); +} +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/blood_pressure_tab.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/blood_pressure_tab.dart new file mode 100644 index 00000000..6c4f892e --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/blood_pressure_tab.dart @@ -0,0 +1,89 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../domain/entities/heartbeat_entity.dart'; +import '../health_colors.dart'; +import '../state/health_view_model.dart'; +import 'health_chart_helpers.dart'; +import 'health_empty_state.dart'; +import 'health_history_section.dart'; +import 'health_line_chart.dart'; + +class BloodPressureTab extends ConsumerWidget { + final List chartData; + final List historyData; + final bool hasMore; + final bool isLoadingMore; + + const BloodPressureTab({ + super.key, + required this.chartData, + required this.historyData, + required this.hasMore, + required this.isLoadingMore, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final vm = ref.read(healthViewModelProvider.notifier); + + final chartWithPressure = chartData + .where( + (h) => h.highBloodPressure != null && h.lowBloodPressure != null, + ) + .toList(); + final historyWithPressure = historyData + .where( + (h) => h.highBloodPressure != null && h.lowBloodPressure != null, + ) + .toList(); + + if (chartWithPressure.isEmpty && historyWithPressure.isEmpty) { + return HealthEmptyState( + theme: theme, + icon: Icons.monitor_heart_outlined, + ); + } + + return ListView( + padding: EdgeInsets.symmetric( + vertical: SizeUtils.getByScreen(small: 4, big: 2), + ), + children: [ + HealthLineChart( + spots: toFlSpots( + chartWithPressure, + (h) => h.highBloodPressure!.toDouble(), + ), + lineColor: const Color(0xFFFF5D52), + secondarySpots: toFlSpots( + chartWithPressure, + (h) => h.lowBloodPressure!.toDouble(), + ), + secondaryLineColor: const Color(0xFFFF9800), + theme: theme, + ), + HealthHistorySection( + items: historyWithPressure, + getTimestamp: (h) => h.occurredAt, + buildRecord: (context, item) => ( + value: '${item.highBloodPressure}/${item.lowBloodPressure}', + unit: context.translate(I18n.mmHg), + valueColor: bloodPressureColor( + item.highBloodPressure!, + item.lowBloodPressure!, + ), + ), + hasMore: hasMore, + isLoadingMore: isLoadingMore, + onLoadMore: () => vm.loadMoreHistory(), + theme: theme, + ), + ], + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/day_header.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/day_header.dart new file mode 100644 index 00000000..15ef7603 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/day_header.dart @@ -0,0 +1,32 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:utils/utils.dart'; + +import '../../../../core/presentation/format_date.dart'; + +class DayHeader extends StatelessWidget { + final DateTime date; + final ThemePort theme; + + const DayHeader({super.key, required this.date, required this.theme}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only( + top: SizeUtils.getByScreen(small: 14, big: 12), + bottom: SizeUtils.getByScreen(small: 6, big: 4), + ), + child: Text( + formatDayHeader(context, date), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + fontWeight: FontWeight.w600, + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_chart_helpers.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_chart_helpers.dart new file mode 100644 index 00000000..5ad87fa7 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_chart_helpers.dart @@ -0,0 +1,9 @@ +import 'package:fl_chart/fl_chart.dart'; + +List toFlSpots(List items, double Function(T) getValue) { + return items + .asMap() + .entries + .map((e) => FlSpot(e.key.toDouble(), getValue(e.value))) + .toList(); +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_empty_state.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_empty_state.dart new file mode 100644 index 00000000..f1022cd9 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_empty_state.dart @@ -0,0 +1,53 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +class HealthEmptyState extends StatelessWidget { + final ThemePort theme; + final IconData icon; + + const HealthEmptyState({ + super.key, + required this.theme, + required this.icon, + }); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + icon, + size: SizeUtils.getByScreen(small: 64, big: 60), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.3), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 14)), + Text( + context.translate(I18n.healthEmpty), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 18, big: 17), + fontWeight: FontWeight.w600, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 6)), + Text( + context.translate(I18n.healthEmptyHint), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 13), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_history_section.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_history_section.dart new file mode 100644 index 00000000..fc429877 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_history_section.dart @@ -0,0 +1,103 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../../../core/presentation/format_date.dart'; +import 'day_header.dart'; +import 'health_record_tile.dart'; + +typedef RecordMapper = ({String value, String unit, Color valueColor}); + +class HealthHistorySection extends StatelessWidget { + final List items; + final int Function(T) getTimestamp; + final RecordMapper Function(BuildContext context, T item) buildRecord; + final bool hasMore; + final bool isLoadingMore; + final VoidCallback onLoadMore; + final ThemePort theme; + + const HealthHistorySection({ + super.key, + required this.items, + required this.getTimestamp, + required this.buildRecord, + required this.hasMore, + required this.isLoadingMore, + required this.onLoadMore, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + final groups = groupByDay(items, getTimestamp); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: Text( + context.translate(I18n.history), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 14), + fontWeight: FontWeight.w600, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + ), + ...groups.expand((group) { + final (day, dayItems) = group; + return [ + Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 22, big: 21), + ), + child: DayHeader(date: day, theme: theme), + ), + ...dayItems.map((item) { + final record = buildRecord(context, item); + return Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 22, big: 21), + ).copyWith( + bottom: SizeUtils.getByScreen(small: 8, big: 6), + ), + child: HealthRecordTile( + value: record.value, + unit: record.unit, + date: formatTime(getTimestamp(item)), + valueColor: record.valueColor, + theme: theme, + ), + ); + }), + ]; + }), + if (hasMore) + Padding( + padding: EdgeInsets.all( + SizeUtils.getByScreen(small: 16, big: 14), + ), + child: Center( + child: isLoadingMore + ? const CircularProgressIndicator() + : TextButton( + onPressed: onLoadMore, + child: Text( + context.translate(I18n.loadMore), + style: TextStyle( + color: theme.getColorFor(ThemeCode.legacyPrimary), + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + ], + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_line_chart.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_line_chart.dart new file mode 100644 index 00000000..41e4cfbf --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_line_chart.dart @@ -0,0 +1,149 @@ +import 'package:design_system/design_system.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:utils/utils.dart'; + +class HealthLineChart extends StatelessWidget { + final List spots; + final Color lineColor; + final ThemePort theme; + + final List? secondarySpots; + final Color? secondaryLineColor; + + const HealthLineChart({ + super.key, + required this.spots, + required this.lineColor, + required this.theme, + this.secondarySpots, + this.secondaryLineColor, + }); + + @override + Widget build(BuildContext context) { + if (spots.isEmpty) { + return SizedBox( + height: SizeUtils.getByScreen(small: 180, big: 160), + child: Center( + child: Text( + '--', + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 16, big: 14), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.3), + ), + ), + ), + ); + } + + final lines = [ + _buildLine(spots, lineColor), + if (secondarySpots != null && secondarySpots!.isNotEmpty) + _buildLine(secondarySpots!, secondaryLineColor ?? lineColor), + ]; + + return Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: SizedBox( + height: SizeUtils.getByScreen(small: 180, big: 160), + child: LineChart( + LineChartData( + lineBarsData: lines, + gridData: FlGridData( + show: true, + drawVerticalLine: false, + horizontalInterval: _computeInterval(spots), + getDrawingHorizontalLine: (value) => FlLine( + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.08), + strokeWidth: 1, + ), + ), + titlesData: FlTitlesData( + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: SizeUtils.getByScreen(small: 36, big: 32), + getTitlesWidget: (value, meta) => Text( + value.toInt().toString(), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 10, big: 9), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.4), + ), + ), + ), + ), + bottomTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + topTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + rightTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + ), + borderData: FlBorderData(show: false), + lineTouchData: LineTouchData( + touchTooltipData: LineTouchTooltipData( + getTooltipColor: (_) => + theme.getColorFor(ThemeCode.backgroundSecondary), + getTooltipItems: (spots) => spots + .map( + (spot) => LineTooltipItem( + spot.y.toInt().toString(), + TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11), + fontWeight: FontWeight.w600, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + ) + .toList(), + ), + ), + ), + ), + ), + ); + } + + LineChartBarData _buildLine(List data, Color color) { + return LineChartBarData( + spots: data, + isCurved: true, + preventCurveOverShooting: true, + color: color, + barWidth: 2, + dotData: FlDotData( + show: data.length <= 30, + getDotPainter: (spot, percent, bar, index) => FlDotCirclePainter( + radius: 3, + color: color, + strokeWidth: 0, + ), + ), + belowBarData: BarAreaData( + show: true, + color: color.withValues(alpha: 0.1), + ), + ); + } + + double _computeInterval(List data) { + if (data.length < 2) return 1; + final yValues = data.map((s) => s.y); + final range = yValues.reduce((a, b) => a > b ? a : b) - + yValues.reduce((a, b) => a < b ? a : b); + if (range <= 0) return 1; + return (range / 4).ceilToDouble(); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_record_tile.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_record_tile.dart new file mode 100644 index 00000000..59cc67a5 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_record_tile.dart @@ -0,0 +1,75 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:utils/utils.dart'; + +class HealthRecordTile extends StatelessWidget { + final String value; + final String unit; + final String date; + final Color valueColor; + final ThemePort theme; + + const HealthRecordTile({ + super.key, + required this.value, + required this.unit, + required this.date, + required this.valueColor, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + vertical: SizeUtils.getByScreen(small: 12, big: 10), + ), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundSecondary), + borderRadius: BorderRadius.all( + Radius.circular(SizeUtils.getByScreen(small: 12, big: 10)), + ), + ), + child: Row( + children: [ + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.baseline, + textBaseline: TextBaseline.alphabetic, + children: [ + Text( + value, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 24, big: 22), + fontWeight: FontWeight.w700, + color: valueColor, + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 4, big: 4)), + Text( + unit, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + ], + ), + ), + Text( + date, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_stats_row.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_stats_row.dart new file mode 100644 index 00000000..88518262 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_stats_row.dart @@ -0,0 +1,114 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../state/health_view_state.dart'; + +class HealthStatsRow extends StatelessWidget { + final HealthStats stats; + final String unit; + final ThemePort theme; + + const HealthStatsRow({ + super.key, + required this.stats, + required this.unit, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + final bool hasData = stats.avg > 0; + + return Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + vertical: SizeUtils.getByScreen(small: 8, big: 6), + ), + child: Row( + children: [ + Expanded( + child: _StatItem( + label: context.translate(I18n.average), + value: hasData ? '${stats.avg}' : '--', + unit: unit, + theme: theme, + ), + ), + Expanded( + child: _StatItem( + label: context.translate(I18n.minimum), + value: hasData ? '${stats.min}' : '--', + unit: unit, + theme: theme, + ), + ), + Expanded( + child: _StatItem( + label: context.translate(I18n.maximum), + value: hasData ? '${stats.max}' : '--', + unit: unit, + theme: theme, + ), + ), + ], + ), + ); + } +} + +class _StatItem extends StatelessWidget { + final String label; + final String value; + final String unit; + final ThemePort theme; + + const _StatItem({ + required this.label, + required this.value, + required this.unit, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Text( + label, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 11, big: 10), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 4, big: 2)), + RichText( + text: TextSpan( + children: [ + TextSpan( + text: value, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 18), + fontWeight: FontWeight.w700, + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + TextSpan( + text: ' $unit', + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 11, big: 10), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + ], + ), + ), + ], + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_summary_cards.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_summary_cards.dart new file mode 100644 index 00000000..76ffb62e --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/health_summary_cards.dart @@ -0,0 +1,176 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../domain/entities/heartbeat_entity.dart'; +import '../../domain/entities/oxygen_entity.dart'; +import '../../../../core/presentation/format_date.dart'; +import '../health_colors.dart'; + +class HealthSummaryCards extends StatelessWidget { + final List heartbeats; + final List oxygens; + final TabController tabController; + final ThemePort theme; + + const HealthSummaryCards({ + super.key, + required this.heartbeats, + required this.oxygens, + required this.tabController, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + final lastHeartbeat = heartbeats.isNotEmpty ? heartbeats.first : null; + final lastWithPressure = heartbeats + .where( + (h) => h.highBloodPressure != null && h.lowBloodPressure != null, + ) + .firstOrNull; + final lastOxygen = oxygens.isNotEmpty ? oxygens.first : null; + + return Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + vertical: SizeUtils.getByScreen(small: 12, big: 10), + ), + child: Row( + children: [ + Expanded( + child: _SummaryCard( + onTap: () => tabController.animateTo(0), + icon: Icons.favorite_rounded, + value: lastHeartbeat != null ? '${lastHeartbeat.heartbeats}' : '--', + unit: context.translate(I18n.bpm), + timeAgo: lastHeartbeat != null + ? formatTimeAgo(context, lastHeartbeat.occurredAt) + : '', + valueColor: lastHeartbeat != null + ? heartRateColor(lastHeartbeat.heartbeats) + : theme.getColorFor(ThemeCode.textPrimary).withValues(alpha: 0.3), + theme: theme, + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 8, big: 6)), + Expanded( + child: _SummaryCard( + onTap: () => tabController.animateTo(1), + icon: Icons.monitor_heart_outlined, + value: lastWithPressure != null + ? '${lastWithPressure.highBloodPressure}/${lastWithPressure.lowBloodPressure}' + : '--', + unit: context.translate(I18n.mmHg), + timeAgo: lastWithPressure != null + ? formatTimeAgo(context, lastWithPressure.occurredAt) + : '', + valueColor: lastWithPressure != null + ? bloodPressureColor( + lastWithPressure.highBloodPressure!, + lastWithPressure.lowBloodPressure!, + ) + : theme.getColorFor(ThemeCode.textPrimary).withValues(alpha: 0.3), + theme: theme, + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 8, big: 6)), + Expanded( + child: _SummaryCard( + onTap: () => tabController.animateTo(2), + icon: Icons.air_rounded, + value: lastOxygen != null ? '${lastOxygen.oxygen}%' : '--', + unit: context.translate(I18n.spo2), + timeAgo: lastOxygen != null + ? formatTimeAgo(context, lastOxygen.occurredAt) + : '', + valueColor: lastOxygen != null + ? oxygenColor(lastOxygen.oxygen) + : theme.getColorFor(ThemeCode.textPrimary).withValues(alpha: 0.3), + theme: theme, + ), + ), + ], + ), + ); + } +} + +class _SummaryCard extends StatelessWidget { + final VoidCallback onTap; + final IconData icon; + final String value; + final String unit; + final String timeAgo; + final Color valueColor; + final ThemePort theme; + + const _SummaryCard({ + required this.onTap, + required this.icon, + required this.value, + required this.unit, + required this.timeAgo, + required this.valueColor, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 10, big: 8), + vertical: SizeUtils.getByScreen(small: 12, big: 10), + ), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundSecondary), + borderRadius: BorderRadius.all( + Radius.circular(SizeUtils.getByScreen(small: 12, big: 10)), + ), + ), + child: Column( + children: [ + Icon( + icon, + color: valueColor, + size: SizeUtils.getByScreen(small: 22, big: 20), + ), + SizedBox(height: SizeUtils.getByScreen(small: 6, big: 4)), + Text( + value, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 18), + fontWeight: FontWeight.w700, + color: valueColor, + ), + ), + Text( + unit, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 11, big: 10), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + if (timeAgo.isNotEmpty) ...[ + SizedBox(height: SizeUtils.getByScreen(small: 4, big: 2)), + Text( + timeAgo, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 10, big: 9), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.4), + ), + ), + ], + ], + ), + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/heart_rate_tab.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/heart_rate_tab.dart new file mode 100644 index 00000000..b7503b46 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/heart_rate_tab.dart @@ -0,0 +1,73 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../domain/entities/heartbeat_entity.dart'; +import '../health_colors.dart'; +import '../state/health_view_model.dart'; +import '../state/health_view_state.dart'; +import 'health_chart_helpers.dart'; +import 'health_empty_state.dart'; +import 'health_history_section.dart'; +import 'health_line_chart.dart'; +import 'health_stats_row.dart'; + +class HeartRateTab extends ConsumerWidget { + final List chartData; + final List historyData; + final HealthStats stats; + final bool hasMore; + final bool isLoadingMore; + + const HeartRateTab({ + super.key, + required this.chartData, + required this.historyData, + required this.stats, + required this.hasMore, + required this.isLoadingMore, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final vm = ref.read(healthViewModelProvider.notifier); + + if (chartData.isEmpty && historyData.isEmpty) { + return HealthEmptyState(theme: theme, icon: Icons.favorite_rounded); + } + + return ListView( + padding: EdgeInsets.symmetric( + vertical: SizeUtils.getByScreen(small: 4, big: 2), + ), + children: [ + HealthLineChart( + spots: toFlSpots(chartData, (h) => h.heartbeats.toDouble()), + lineColor: const Color(0xFFFF5D52), + theme: theme, + ), + HealthStatsRow( + stats: stats, + unit: context.translate(I18n.bpm), + theme: theme, + ), + HealthHistorySection( + items: historyData, + getTimestamp: (h) => h.occurredAt, + buildRecord: (context, item) => ( + value: '${item.heartbeats}', + unit: context.translate(I18n.bpm), + valueColor: heartRateColor(item.heartbeats), + ), + hasMore: hasMore, + isLoadingMore: isLoadingMore, + onLoadMore: () => vm.loadMoreHistory(), + theme: theme, + ), + ], + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/oxygen_tab.dart b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/oxygen_tab.dart new file mode 100644 index 00000000..9d25e78c --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/health/presentation/widgets/oxygen_tab.dart @@ -0,0 +1,73 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../domain/entities/oxygen_entity.dart'; +import '../health_colors.dart'; +import '../state/health_view_model.dart'; +import '../state/health_view_state.dart'; +import 'health_chart_helpers.dart'; +import 'health_empty_state.dart'; +import 'health_history_section.dart'; +import 'health_line_chart.dart'; +import 'health_stats_row.dart'; + +class OxygenTab extends ConsumerWidget { + final List chartData; + final List historyData; + final HealthStats stats; + final bool hasMore; + final bool isLoadingMore; + + const OxygenTab({ + super.key, + required this.chartData, + required this.historyData, + required this.stats, + required this.hasMore, + required this.isLoadingMore, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final vm = ref.read(healthViewModelProvider.notifier); + + if (chartData.isEmpty && historyData.isEmpty) { + return HealthEmptyState(theme: theme, icon: Icons.air_rounded); + } + + return ListView( + padding: EdgeInsets.symmetric( + vertical: SizeUtils.getByScreen(small: 4, big: 2), + ), + children: [ + HealthLineChart( + spots: toFlSpots(chartData, (o) => o.oxygen.toDouble()), + lineColor: const Color(0xFF4CAF50), + theme: theme, + ), + HealthStatsRow( + stats: stats, + unit: context.translate(I18n.spo2), + theme: theme, + ), + HealthHistorySection( + items: historyData, + getTimestamp: (o) => o.occurredAt, + buildRecord: (context, item) => ( + value: '${item.oxygen}%', + unit: context.translate(I18n.spo2), + valueColor: oxygenColor(item.oxygen), + ), + hasMore: hasMore, + isLoadingMore: isLoadingMore, + onLoadMore: () => vm.loadMoreHistory(), + theme: theme, + ), + ], + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/locate_device/locate_device_builder.dart b/modules/legacy/modules/device_management/lib/src/features/locate_device/locate_device_builder.dart index 7da9f2fa..62feaaa9 100644 --- a/modules/legacy/modules/device_management/lib/src/features/locate_device/locate_device_builder.dart +++ b/modules/legacy/modules/device_management/lib/src/features/locate_device/locate_device_builder.dart @@ -1,18 +1,15 @@ import 'package:flutter/material.dart'; -import 'package:device_management/src/features/locate_device/presentation/locate_device_screen.dart'; import 'package:go_router/go_router.dart'; -import 'package:get_it/get_it.dart'; -import 'package:navigation/navigation.dart'; + +import 'presentation/locate_device_screen.dart'; class LocateDeviceBuilder { const LocateDeviceBuilder(); Page buildPage(BuildContext context, GoRouterState state) { - final NavigationContract navigationContract = GetIt.I(); - return MaterialPage( key: state.pageKey, - child: LocateDeviceScreen(navigationContract: navigationContract), + child: const LocateDeviceScreen(), ); } } diff --git a/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/locate_device_screen.dart b/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/locate_device_screen.dart index f7f27bb8..5723921a 100644 --- a/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/locate_device_screen.dart +++ b/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/locate_device_screen.dart @@ -1,63 +1,86 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:device_management/src/features/locate_device/presentation/widgets/locate_device_dialog.dart'; -import 'package:navigation/navigation.dart'; +import 'package:legacy_shared/legacy_shared.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; -import 'package:legacy_shared/legacy_shared.dart'; + +import 'state/locate_device_view_model.dart'; +import 'widgets/locate_device_dialog.dart'; class LocateDeviceScreen extends ConsumerWidget { - final NavigationContract navigationContract; - - const LocateDeviceScreen({super.key, required this.navigationContract}); + const LocateDeviceScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.watch(themePortProvider); + ref.listen( + locateDeviceViewModelProvider.select((s) => s.errorMessage), + (previous, next) { + if (next.isNotEmpty) { + showTopSnackbar(context, message: next, type: MessageType.error); + } + }, + ); + + ref.listen( + locateDeviceViewModelProvider.select((s) => s.isComplete), + (previous, next) { + if (next) { + showTopSnackbar( + context, + message: context.translate(I18n.sentSuccessfully), + type: MessageType.success, + ); + } + }, + ); + return LegacyPageLayout( theme: theme, title: context.translate(I18n.locateSF), - body: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 16), - big: EdgeInsets.symmetric(horizontal: 15) + body: Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 15), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(context.translate(I18n.locateSFBody1), + Text( + context.translate(I18n.locateSFBody1), style: TextStyle( fontSize: SizeUtils.getByScreen(small: 18, big: 17), fontWeight: FontWeight.w500, - ) + ), ), SizedBox(height: SizeUtils.getByScreen(small: 10, big: 8)), - Text(context.translate(I18n.locateSFBody2), + Text( + context.translate(I18n.locateSFBody2), style: TextStyle( - fontSize: 16 - )) + fontSize: SizeUtils.getByScreen(small: 16, big: 15), + ), + ), ], ), ), - footer: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(vertical: 12, horizontal: 26), - big: EdgeInsets.symmetric(vertical: 10, horizontal: 25) + footer: Padding( + padding: EdgeInsets.symmetric( + vertical: SizeUtils.getByScreen(small: 12, big: 10), + horizontal: SizeUtils.getByScreen(small: 26, big: 25), ), child: PrimaryButton( onPressed: () { - showDialog(context: context, builder: (context)=>Dialog( - child: LocateDialog(), - )); + showDialog( + context: context, + builder: (_) => const Dialog(child: LocateDeviceDialog()), + ); }, text: context.translate(I18n.locateSFAction), color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 36, big: 35), ), - ) + ), ); } -} \ No newline at end of file +} diff --git a/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/state/locate_device_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/state/locate_device_view_model.dart index 4e26897f..3d3609df 100644 --- a/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/state/locate_device_view_model.dart +++ b/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/state/locate_device_view_model.dart @@ -1,34 +1,23 @@ -import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:device_management/src/features/locate_device/presentation/state/locate_device_view_state.dart'; import 'package:legacy_shared/legacy_shared.dart'; +import 'locate_device_view_state.dart'; + final locateDeviceViewModelProvider = - NotifierProvider.autoDispose( - LocateDeviceViewModel.new, - ); + NotifierProvider.autoDispose( + LocateDeviceViewModel.new, +); class LocateDeviceViewModel extends Notifier { late final CommandsRepository _commandsRepository; - late final TextEditingController nameController; - late final TextEditingController phoneController; - @override LocateDeviceViewState build() { _commandsRepository = ref.read(commandsRepositoryProvider); - state = const LocateDeviceViewState(); + final device = ref.read(selectedDeviceProvider); - _init(); - - return state; - } - - Future _init() async { - final selectedDevice = ref.read(selectedDeviceProvider); - if (!ref.mounted) return; - state = state.copyWith(device: selectedDevice); + return LocateDeviceViewState(device: device); } Future locateDevice() async { @@ -41,13 +30,13 @@ class LocateDeviceViewModel extends Notifier { errorMessage: '', ); - final request = SendCommandRequestModel(device: state.device!.identificator, command: 'FIND_DEVICE'); + final request = SendCommandRequestModel( + device: state.device!.identificator, + command: DeviceCommand.findDevice, + ); await _commandsRepository.send(request: request); - state = state.copyWith( - isLoading: false, - isComplete: true, - ); + state = state.copyWith(isLoading: false, isComplete: true); } catch (e) { state = state.copyWith( isLoading: false, @@ -57,10 +46,7 @@ class LocateDeviceViewModel extends Notifier { } } - void endLocation() { - state = state.copyWith( - errorMessage: '', - - ); + void resetError() { + state = state.copyWith(errorMessage: ''); } } diff --git a/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/state/locate_device_view_state.dart b/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/state/locate_device_view_state.dart index 03e63fc2..a9bd6a3c 100644 --- a/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/state/locate_device_view_state.dart +++ b/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/state/locate_device_view_state.dart @@ -1,5 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:sf_shared/sf_shared.dart'; + part 'locate_device_view_state.freezed.dart'; @freezed diff --git a/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/widgets/locate_device_dialog.dart b/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/widgets/locate_device_dialog.dart index 9375384d..d43d7239 100644 --- a/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/widgets/locate_device_dialog.dart +++ b/modules/legacy/modules/device_management/lib/src/features/locate_device/presentation/widgets/locate_device_dialog.dart @@ -1,64 +1,62 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:device_management/src/features/locate_device/presentation/state/locate_device_view_model.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; -class LocateDialog extends ConsumerWidget { +import '../state/locate_device_view_model.dart'; + +class LocateDeviceDialog extends ConsumerWidget { + const LocateDeviceDialog({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.watch(themePortProvider); - - final viewModel = ref.read(locateDeviceViewModelProvider.notifier); - final viewState = ref.watch(locateDeviceViewModelProvider); + final state = ref.watch(locateDeviceViewModelProvider); + final vm = ref.read(locateDeviceViewModelProvider.notifier); return Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 32, vertical: 30), - big: EdgeInsets.symmetric(horizontal: 30, vertical: 28) + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 32, big: 30), + vertical: SizeUtils.getByScreen(small: 30, big: 28), ), width: SizeUtils.getByScreen(small: 360, big: 350), - height: SizeUtils.getByScreen(small: 210, big: 205), child: Column( + mainAxisSize: MainAxisSize.min, children: [ - if (viewState.isLoading) - Expanded(child: Center(child: Text(context.translate('Sending...'), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 25, big: 24), - ), - ))), - if (!viewState.isLoading && viewState.isComplete) - Expanded(child: Center(child: Text(context.translate('Sent successfully'), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 25, big: 24), - ), - ))), - if (!viewState.isComplete && viewState.errorMessage.isNotEmpty) ...[ - Expanded(child: Center(child: Text(context.translate('The device is not connected to the Internet'), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 20, big: 19), - ), - ))), + if (state.isLoading) + _DialogMessage( + text: context.translate(I18n.sending), + theme: theme, + ), + if (!state.isLoading && state.isComplete) + _DialogMessage( + text: context.translate(I18n.sentSuccessfully), + theme: theme, + ), + if (state.errorMessage.isNotEmpty) ...[ + _DialogMessage( + text: context.translate(I18n.deviceNotConnected), + theme: theme, + fontSize: SizeUtils.getByScreen(small: 20, big: 19), + ), SizedBox(height: SizeUtils.getByScreen(small: 24, big: 23)), - Expanded(child: PrimaryButton( - onPressed: (){ + PrimaryButton( + onPressed: () { Navigator.pop(context); - viewModel.endLocation(); + vm.resetError(); }, - text: context.translate('OK'), + text: context.translate(I18n.ok), color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 38, big: 36), radius: SizeUtils.getByScreen(small: 32, big: 34), - )), + ), ], - if (!viewState.isComplete && !viewState.isLoading && viewState.errorMessage.isEmpty) ...[ - Text(context.translate('You are going to activate the remote location of your device. It will start ringing.'), + if (!state.isComplete && + !state.isLoading && + state.errorMessage.isEmpty) ...[ + Text( + context.translate(I18n.locateDeviceConfirmMessage), textAlign: TextAlign.center, style: TextStyle( fontSize: SizeUtils.getByScreen(small: 19, big: 18), @@ -66,30 +64,59 @@ class LocateDialog extends ConsumerWidget { ), SizedBox(height: SizeUtils.getByScreen(small: 24, big: 23)), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded(child: PrimaryButton( - onPressed: (){Navigator.pop(context);}, - text: context.translate(I18n.cancel), - color: theme.getColorFor(ThemeCode.legacyPrimary), - height: SizeUtils.getByScreen(small: 38, big: 36), - radius: SizeUtils.getByScreen(small: 32, big: 34), - )), - SizedBox(width: SizeUtils.getByScreen(small: 4, big: 16)), - Expanded(child: PrimaryButton( - onPressed: () { - viewModel.locateDevice(); - }, - text: context.translate(I18n.accept), - color: theme.getColorFor(ThemeCode.legacyPrimary), - height: SizeUtils.getByScreen(small: 38, big: 36), - radius: SizeUtils.getByScreen(small: 32, big: 34), - )) + Expanded( + child: PrimaryButton( + onPressed: () => Navigator.pop(context), + text: context.translate(I18n.cancel), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: SizeUtils.getByScreen(small: 38, big: 36), + radius: SizeUtils.getByScreen(small: 32, big: 34), + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 8, big: 16)), + Expanded( + child: PrimaryButton( + onPressed: vm.locateDevice, + text: context.translate(I18n.accept), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: SizeUtils.getByScreen(small: 38, big: 36), + radius: SizeUtils.getByScreen(small: 32, big: 34), + ), + ), ], - ) - ] + ), + ], ], ), ); } -} \ No newline at end of file +} + +class _DialogMessage extends StatelessWidget { + final String text; + final ThemePort theme; + final double? fontSize; + + const _DialogMessage({ + required this.text, + required this.theme, + this.fontSize, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.symmetric( + vertical: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: Text( + text, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: fontSize ?? SizeUtils.getByScreen(small: 25, big: 24), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/remote_camera_screen.dart b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/remote_camera_screen.dart index f37d8907..96bbe230 100644 --- a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/remote_camera_screen.dart +++ b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/remote_camera_screen.dart @@ -112,7 +112,7 @@ class _TakePictureSection extends ConsumerWidget { ), width: SizeUtils.getByScreen(small: 360, big: 350), height: SizeUtils.getByScreen(small: 195, big: 185), - child: Center(child: Text(context.translate('Loading photo...'), + child: Center(child: Text(context.translate(I18n.loadingPhoto), textAlign: TextAlign.center, style: TextStyle(fontSize: SizeUtils.getByScreen(small: 26, big: 25)), )), diff --git a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart index 98512933..24c8ed27 100644 --- a/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart +++ b/modules/legacy/modules/device_management/lib/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart @@ -65,7 +65,7 @@ class _Header extends StatelessWidget { Widget build(BuildContext context) { return Stack( children: [ - Center(child: Text(context.translate('Remote listening'), + Center(child: Text(context.translate(I18n.remoteListening), textAlign: TextAlign.center, style: TextStyle(fontSize: SizeUtils.getByScreen(small: 19, big: 18)), )), diff --git a/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/rewards_screen.dart b/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/rewards_screen.dart index 252c8c3f..c4aa2adb 100644 --- a/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/rewards_screen.dart +++ b/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/rewards_screen.dart @@ -1,21 +1,42 @@ import 'package:design_system/design_system.dart'; -import 'package:device_management/src/features/rewards/presentation/state/rewards_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:legacy_shared/legacy_shared.dart'; -import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import 'state/rewards_view_model.dart'; class RewardsScreen extends ConsumerWidget { - - final NavigationContract navigationContract; - - const RewardsScreen({super.key, required this.navigationContract}); + const RewardsScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final state = ref.watch(rewardsViewModelProvider); + final vm = ref.read(rewardsViewModelProvider.notifier); - final theme = ref.read(themePortProvider); + ref.listen( + rewardsViewModelProvider.select((s) => s.errorMessage), + (previous, next) { + if (next.isNotEmpty) { + showTopSnackbar(context, message: next, type: MessageType.error); + } + }, + ); + + ref.listen( + rewardsViewModelProvider.select((s) => s.isComplete), + (previous, next) { + if (next) { + showTopSnackbar( + context, + message: context.translate(I18n.rewardsSent), + type: MessageType.success, + ); + } + }, + ); return LegacyPageLayout( theme: theme, @@ -23,37 +44,45 @@ class RewardsScreen extends ConsumerWidget { body: Column( children: [ Center( - child: Icon(SFIcons.rewardsCircle, - size: 180, + child: Icon( + SFIcons.rewardsCircle, + size: SizeUtils.getByScreen(small: 180, big: 160), color: theme.getColorFor(ThemeCode.legacyPrimary), - ) + ), ), - SizedBox(height: 32), + SizedBox(height: SizeUtils.getByScreen(small: 32, big: 28)), Text( context.translate(I18n.rewardsMessage), textAlign: TextAlign.start, ), - SizedBox(height: 12), - const _CounterSection(), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), + _CounterSection(theme: theme), ], ), - footer: _SaveSection(), + footer: Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 24, big: 22), + vertical: SizeUtils.getByScreen(small: 10, big: 8), + ), + child: PrimaryButton( + onPressed: state.isLoading ? null : vm.submit, + text: context.translate(I18n.sendRewards), + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), + ), ); } } class _CounterSection extends ConsumerWidget { + final ThemePort theme; - const _CounterSection(); + const _CounterSection({required this.theme}); @override Widget build(BuildContext context, WidgetRef ref) { - - final theme = ref.read(themePortProvider); - - final state = ref.watch(rewardsViewModelProvider); final vm = ref.read(rewardsViewModelProvider.notifier); - + return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -63,7 +92,7 @@ class _CounterSection extends ConsumerWidget { color: theme.getColorFor(ThemeCode.legacyPrimary), ), SizedBox( - width: 240, + width: SizeUtils.getByScreen(small: 240, big: 220), child: TextField( controller: vm.amountController, decoration: InputDecoration( @@ -71,13 +100,17 @@ class _CounterSection extends ConsumerWidget { borderSide: BorderSide( color: theme.getColorFor(ThemeCode.legacyPrimary), ), - borderRadius: BorderRadius.all(Radius.circular(32)), + borderRadius: BorderRadius.all( + Radius.circular(SizeUtils.getByScreen(small: 32, big: 28)), + ), ), ), - style: TextStyle(color: theme.getColorFor(ThemeCode.legacyPrimary)), + style: TextStyle( + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), textAlign: TextAlign.center, keyboardType: TextInputType.number, - ) + ), ), IconButton( onPressed: vm.increaseAmount, @@ -87,39 +120,4 @@ class _CounterSection extends ConsumerWidget { ], ); } -} - -class _SaveSection extends ConsumerWidget{ - - const _SaveSection(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - final vm = ref.read(rewardsViewModelProvider.notifier); - - return Padding( - padding: EdgeInsets.symmetric(horizontal: 24, vertical: 10), - child: PrimaryButton( - onPressed: () async { - await vm.submit(); - - final errorMessage = ref.read( - rewardsViewModelProvider.select((s)=>s.errorMessage) - ); - - if (errorMessage.isNotEmpty) { - showTopSnackbar( - context, - message: errorMessage, - type: MessageType.error, - ); - } - }, - text: context.translate(I18n.sendRewards), - color: theme.getColorFor(ThemeCode.legacyPrimary) - ) - ); - } } \ No newline at end of file diff --git a/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/state/rewards_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/state/rewards_view_model.dart index d1a6edb0..68c6d176 100644 --- a/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/state/rewards_view_model.dart +++ b/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/state/rewards_view_model.dart @@ -4,57 +4,44 @@ import 'package:legacy_shared/legacy_shared.dart'; import 'rewards_view_state.dart'; - final rewardsViewModelProvider = -NotifierProvider.autoDispose( + NotifierProvider.autoDispose( RewardsViewModel.new, ); class RewardsViewModel extends Notifier { - - static final _min = 1; + static const _min = 1; late final TextEditingController amountController; late final CommandsRepository _commandsRepository; @override RewardsViewState build() { - _commandsRepository = ref.read(commandsRepositoryProvider); - amountController = TextEditingController(); + amountController = TextEditingController(text: '1'); amountController.addListener(_onAmountChanged); - amountController.text = '1'; - ref.onDispose(disposeControllers); + ref.onDispose(_disposeControllers); return const RewardsViewState(); } void _onAmountChanged() { final raw = amountController.text; - if (raw.isEmpty) return; final amount = int.tryParse(raw); - if (amount == null) return; if (amount == state.amount) return; if (amount < _min) return; - state = state.copyWith( - amount: amount, - errorMessage: '', - ); + state = state.copyWith(amount: amount, errorMessage: ''); } void increaseAmount() { final amount = state.amount + 1; - - state = state.copyWith( - amount: amount, - errorMessage: '', - ); + state = state.copyWith(amount: amount, errorMessage: ''); amountController.text = amount.toString(); } @@ -62,47 +49,34 @@ class RewardsViewModel extends Notifier { if (state.amount == _min) return; final amount = state.amount - 1; - - state = state.copyWith( - amount: amount, - errorMessage: '', - ); + state = state.copyWith(amount: amount, errorMessage: ''); amountController.text = amount.toString(); } Future submit() async { - try { - state = state.copyWith( - isLoading: true, - isComplete: false, - ); + state = state.copyWith(isLoading: true, isComplete: false); final device = ref.read(selectedDeviceProvider); final request = SendCommandRequestModel( device: device!.identificator.toString(), - command: 'REWARDS', - data: { - 'rewards': state.amount - } + command: DeviceCommand.rewards, + data: {'amount': state.amount}, ); await _commandsRepository.send(request: request); - state = state.copyWith( - isLoading: false, - isComplete: true - ); - } catch(e) { + state = state.copyWith(isLoading: false, isComplete: true); + } catch (e) { state = state.copyWith( errorMessage: e.toString(), isLoading: false, - isComplete: false + isComplete: false, ); } } - void disposeControllers() { + void _disposeControllers() { amountController.removeListener(_onAmountChanged); amountController.dispose(); } diff --git a/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/state/rewards_view_state.dart b/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/state/rewards_view_state.dart index 92946970..bbc95aa6 100644 --- a/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/state/rewards_view_state.dart +++ b/modules/legacy/modules/device_management/lib/src/features/rewards/presentation/state/rewards_view_state.dart @@ -10,6 +10,4 @@ abstract class RewardsViewState with _$RewardsViewState { @Default(false) bool isComplete, @Default('') String errorMessage, }) = _RewardsViewState; - - } \ No newline at end of file diff --git a/modules/legacy/modules/device_management/lib/src/features/rewards/rewards_builder.dart b/modules/legacy/modules/device_management/lib/src/features/rewards/rewards_builder.dart index 63cff1a2..e558fc73 100644 --- a/modules/legacy/modules/device_management/lib/src/features/rewards/rewards_builder.dart +++ b/modules/legacy/modules/device_management/lib/src/features/rewards/rewards_builder.dart @@ -1,18 +1,15 @@ -import 'package:device_management/src/features/rewards/presentation/rewards_screen.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:get_it/get_it.dart'; -import 'package:navigation/navigation.dart'; + +import 'presentation/rewards_screen.dart'; class RewardsBuilder { const RewardsBuilder(); Page buildPage(BuildContext context, GoRouterState state) { - final NavigationContract navigationContract = GetIt.I(); - return MaterialPage( key: state.pageKey, - child: RewardsScreen(navigationContract: navigationContract), + child: const RewardsScreen(), ); } } diff --git a/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/domain/entities/scheduled_activity_entity.dart b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/domain/entities/scheduled_activity_entity.dart new file mode 100644 index 00000000..1870023b --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/domain/entities/scheduled_activity_entity.dart @@ -0,0 +1,44 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'scheduled_activity_entity.freezed.dart'; + +@freezed +abstract class ScheduledActivityEntity with _$ScheduledActivityEntity { + const ScheduledActivityEntity._(); + + const factory ScheduledActivityEntity({ + required String id, + required String deviceId, + required int weekDay, + required String name, + required String period, + required int createdAt, + int? updatedAt, + }) = _ScheduledActivityEntity; + + bool get hasValidPeriod => period.length == 8; + + String get startTime => hasValidPeriod + ? '${period.substring(0, 2)}:${period.substring(2, 4)}' + : '--:--'; + + String get endTime => hasValidPeriod + ? '${period.substring(4, 6)}:${period.substring(6, 8)}' + : '--:--'; + + int get startMinutes => hasValidPeriod + ? int.parse(period.substring(0, 2)) * 60 + + int.parse(period.substring(2, 4)) + : 0; + + int get endMinutes => hasValidPeriod + ? int.parse(period.substring(4, 6)) * 60 + + int.parse(period.substring(6, 8)) + : 0; + + bool overlapsWith(ScheduledActivityEntity other) { + if (weekDay != other.weekDay) return false; + if (!hasValidPeriod || !other.hasValidPeriod) return false; + return startMinutes < other.endMinutes && other.startMinutes < endMinutes; + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/domain/entities/scheduled_activity_entity.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/domain/entities/scheduled_activity_entity.freezed.dart new file mode 100644 index 00000000..2fba4320 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/domain/entities/scheduled_activity_entity.freezed.dart @@ -0,0 +1,289 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'scheduled_activity_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$ScheduledActivityEntity { + + String get id; String get deviceId; int get weekDay; String get name; String get period; int get createdAt; int? get updatedAt; +/// Create a copy of ScheduledActivityEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ScheduledActivityEntityCopyWith get copyWith => _$ScheduledActivityEntityCopyWithImpl(this as ScheduledActivityEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ScheduledActivityEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.weekDay, weekDay) || other.weekDay == weekDay)&&(identical(other.name, name) || other.name == name)&&(identical(other.period, period) || other.period == period)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,weekDay,name,period,createdAt,updatedAt); + +@override +String toString() { + return 'ScheduledActivityEntity(id: $id, deviceId: $deviceId, weekDay: $weekDay, name: $name, period: $period, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class $ScheduledActivityEntityCopyWith<$Res> { + factory $ScheduledActivityEntityCopyWith(ScheduledActivityEntity value, $Res Function(ScheduledActivityEntity) _then) = _$ScheduledActivityEntityCopyWithImpl; +@useResult +$Res call({ + String id, String deviceId, int weekDay, String name, String period, int createdAt, int? updatedAt +}); + + + + +} +/// @nodoc +class _$ScheduledActivityEntityCopyWithImpl<$Res> + implements $ScheduledActivityEntityCopyWith<$Res> { + _$ScheduledActivityEntityCopyWithImpl(this._self, this._then); + + final ScheduledActivityEntity _self; + final $Res Function(ScheduledActivityEntity) _then; + +/// Create a copy of ScheduledActivityEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceId = null,Object? weekDay = null,Object? name = null,Object? period = null,Object? createdAt = null,Object? updatedAt = freezed,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,weekDay: null == weekDay ? _self.weekDay : weekDay // ignore: cast_nullable_to_non_nullable +as int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,period: null == period ? _self.period : period // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [ScheduledActivityEntity]. +extension ScheduledActivityEntityPatterns on ScheduledActivityEntity { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _ScheduledActivityEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _ScheduledActivityEntity() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _ScheduledActivityEntity value) $default,){ +final _that = this; +switch (_that) { +case _ScheduledActivityEntity(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ScheduledActivityEntity value)? $default,){ +final _that = this; +switch (_that) { +case _ScheduledActivityEntity() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceId, int weekDay, String name, String period, int createdAt, int? updatedAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _ScheduledActivityEntity() when $default != null: +return $default(_that.id,_that.deviceId,_that.weekDay,_that.name,_that.period,_that.createdAt,_that.updatedAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceId, int weekDay, String name, String period, int createdAt, int? updatedAt) $default,) {final _that = this; +switch (_that) { +case _ScheduledActivityEntity(): +return $default(_that.id,_that.deviceId,_that.weekDay,_that.name,_that.period,_that.createdAt,_that.updatedAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceId, int weekDay, String name, String period, int createdAt, int? updatedAt)? $default,) {final _that = this; +switch (_that) { +case _ScheduledActivityEntity() when $default != null: +return $default(_that.id,_that.deviceId,_that.weekDay,_that.name,_that.period,_that.createdAt,_that.updatedAt);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _ScheduledActivityEntity extends ScheduledActivityEntity { + const _ScheduledActivityEntity({required this.id, required this.deviceId, required this.weekDay, required this.name, required this.period, required this.createdAt, this.updatedAt}): super._(); + + +@override final String id; +@override final String deviceId; +@override final int weekDay; +@override final String name; +@override final String period; +@override final int createdAt; +@override final int? updatedAt; + +/// Create a copy of ScheduledActivityEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ScheduledActivityEntityCopyWith<_ScheduledActivityEntity> get copyWith => __$ScheduledActivityEntityCopyWithImpl<_ScheduledActivityEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ScheduledActivityEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.weekDay, weekDay) || other.weekDay == weekDay)&&(identical(other.name, name) || other.name == name)&&(identical(other.period, period) || other.period == period)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,weekDay,name,period,createdAt,updatedAt); + +@override +String toString() { + return 'ScheduledActivityEntity(id: $id, deviceId: $deviceId, weekDay: $weekDay, name: $name, period: $period, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$ScheduledActivityEntityCopyWith<$Res> implements $ScheduledActivityEntityCopyWith<$Res> { + factory _$ScheduledActivityEntityCopyWith(_ScheduledActivityEntity value, $Res Function(_ScheduledActivityEntity) _then) = __$ScheduledActivityEntityCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceId, int weekDay, String name, String period, int createdAt, int? updatedAt +}); + + + + +} +/// @nodoc +class __$ScheduledActivityEntityCopyWithImpl<$Res> + implements _$ScheduledActivityEntityCopyWith<$Res> { + __$ScheduledActivityEntityCopyWithImpl(this._self, this._then); + + final _ScheduledActivityEntity _self; + final $Res Function(_ScheduledActivityEntity) _then; + +/// Create a copy of ScheduledActivityEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceId = null,Object? weekDay = null,Object? name = null,Object? period = null,Object? createdAt = null,Object? updatedAt = freezed,}) { + return _then(_ScheduledActivityEntity( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,weekDay: null == weekDay ? _self.weekDay : weekDay // ignore: cast_nullable_to_non_nullable +as int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,period: null == period ? _self.period : period // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/scheduled_activities_screen.dart b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/scheduled_activities_screen.dart new file mode 100644 index 00000000..722e3f90 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/scheduled_activities_screen.dart @@ -0,0 +1,121 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:navigation/navigation.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import 'state/scheduled_activities_view_model.dart'; +import 'widgets/activity_form_sheet.dart'; +import 'widgets/day_timeline.dart'; + +class ScheduledActivitiesScreen extends ConsumerStatefulWidget { + final NavigationContract navigationContract; + + const ScheduledActivitiesScreen({ + super.key, + required this.navigationContract, + }); + + @override + ConsumerState createState() => + _ScheduledActivitiesScreenState(); +} + +class _ScheduledActivitiesScreenState + extends ConsumerState + with SingleTickerProviderStateMixin { + late final TabController _tabController; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 7, vsync: this); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + int get _selectedWeekDay => _tabController.index + 1; + + @override + Widget build(BuildContext context) { + final theme = ref.watch(themePortProvider); + final state = ref.watch(scheduledActivitiesViewModelProvider); + + ref.listen( + scheduledActivitiesViewModelProvider.select((s) => s.errorMessage), + (previous, next) { + if (next.isNotEmpty) { + showTopSnackbar(context, message: next, type: MessageType.error); + } + }, + ); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.calendar), + body: state.isLoading + ? const Center(child: CircularProgressIndicator()) + : Column( + children: [ + TabBar( + controller: _tabController, + labelColor: theme.getColorFor(ThemeCode.legacyPrimary), + unselectedLabelColor: + theme.getColorFor(ThemeCode.textPrimary), + indicatorColor: theme.getColorFor(ThemeCode.legacyPrimary), + indicatorWeight: 3, + labelStyle: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + fontWeight: FontWeight.w600, + ), + unselectedLabelStyle: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + fontWeight: FontWeight.w400, + ), + tabs: weekDayI18nKeys.entries + .map((e) => Tab( + text: weekDayShortLabel(context, e.value), + )) + .toList(), + ), + Expanded( + child: TabBarView( + controller: _tabController, + children: List.generate(7, (index) { + final weekDay = index + 1; + final dayActivities = state.activities + .where((a) => a.weekDay == weekDay) + .toList(); + return DayTimeline(activities: dayActivities); + }), + ), + ), + ], + ), + footer: Material( + color: theme.getColorFor(ThemeCode.legacyPrimary), + shape: const CircleBorder(), + child: InkWell( + customBorder: const CircleBorder(), + onTap: () => + showActivityFormSheet(context, weekDay: _selectedWeekDay), + child: SizedBox( + width: SizeUtils.getByScreen(small: 48, big: 46), + height: SizeUtils.getByScreen(small: 48, big: 46), + child: Icon( + Icons.add, + color: Colors.white, + size: SizeUtils.getByScreen(small: 28, big: 26), + ), + ), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/state/scheduled_activities_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/state/scheduled_activities_view_model.dart new file mode 100644 index 00000000..94568a21 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/state/scheduled_activities_view_model.dart @@ -0,0 +1,201 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:uuid/uuid.dart'; + +import '../../../../core/data/models/create_scheduled_activity_request_model.dart'; +import '../../../../core/data/models/update_scheduled_activity_request_model.dart'; +import '../../../../core/domain/repositories/scheduled_activities_repository.dart'; +import '../../../../core/providers/scheduled_activities_repository_provider.dart'; +import '../../domain/entities/scheduled_activity_entity.dart'; +import 'scheduled_activities_view_state.dart'; + +final scheduledActivitiesViewModelProvider = NotifierProvider.autoDispose< + ScheduledActivitiesViewModel, ScheduledActivitiesViewState>( + ScheduledActivitiesViewModel.new, +); + +class ScheduledActivitiesViewModel + extends Notifier { + late final ScheduledActivitiesRepository _repository; + static const _uuid = Uuid(); + + @override + ScheduledActivitiesViewState build() { + _repository = ref.read(scheduledActivitiesRepositoryProvider); + _init(); + return const ScheduledActivitiesViewState(); + } + + String? get _deviceId => ref.read(selectedDeviceProvider)?.id; + + Future _init() async { + if (_deviceId == null) { + state = state.copyWith(isLoading: false); + return; + } + + try { + final activities = await _repository.getActivities(deviceId: _deviceId!); + if (!ref.mounted) return; + + state = state.copyWith( + activities: _sortActivities(activities), + isLoading: false, + ); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } + } + + ScheduledActivityEntity? _findOverlap({ + required int weekDay, + required String period, + String? excludeId, + }) { + final candidate = ScheduledActivityEntity( + id: '', + deviceId: '', + weekDay: weekDay, + name: '', + period: period, + createdAt: 0, + ); + + for (final activity in state.activities) { + if (activity.id == excludeId) continue; + if (activity.overlapsWith(candidate)) return activity; + } + return null; + } + + Future createActivity({ + required String name, + required int weekDay, + required String period, + }) async { + if (_deviceId == null) return; + + final overlap = _findOverlap(weekDay: weekDay, period: period); + if (overlap != null) { + state = state.copyWith(errorMessage: _overlapMessage(overlap)); + return; + } + + try { + state = state.copyWith(isLoading: true, errorMessage: ''); + + final request = CreateScheduledActivityRequestModel( + id: _uuid.v4(), + deviceId: _deviceId!, + weekDay: weekDay, + name: name, + period: period, + ); + + await _repository.createActivity(request: request); + if (!ref.mounted) return; + + await _reload(); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } + } + + Future updateActivity({ + required String activityId, + required int weekDay, + required String name, + required String period, + }) async { + if (_deviceId == null) return; + + final overlap = _findOverlap( + weekDay: weekDay, + period: period, + excludeId: activityId, + ); + if (overlap != null) { + state = state.copyWith(errorMessage: _overlapMessage(overlap)); + return; + } + + try { + state = state.copyWith(isLoading: true, errorMessage: ''); + + final request = UpdateScheduledActivityRequestModel( + deviceId: _deviceId!, + name: name, + period: period, + ); + + await _repository.updateActivity( + activityId: activityId, + request: request, + ); + if (!ref.mounted) return; + + await _reload(); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } + } + + Future deleteActivity(String activityId) async { + try { + state = state.copyWith(isLoading: true, errorMessage: ''); + + await _repository.deleteActivity(activityId: activityId); + if (!ref.mounted) return; + + await _reload(); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } + } + + Future _reload() async { + if (_deviceId == null) return; + + try { + final activities = + await _repository.getActivities(deviceId: _deviceId!); + if (!ref.mounted) return; + + state = state.copyWith( + activities: _sortActivities(activities), + isLoading: false, + ); + } catch (e) { + if (!ref.mounted) return; + state = state.copyWith(isLoading: false, errorMessage: _formatError(e)); + } + } + + List _sortActivities( + List activities, + ) { + return List.of(activities) + ..sort((a, b) { + final dayCompare = a.weekDay.compareTo(b.weekDay); + if (dayCompare != 0) return dayCompare; + return a.startMinutes.compareTo(b.startMinutes); + }); + } + + String _overlapMessage(ScheduledActivityEntity overlap) { + return I18n.scheduledActivityOverlap.tr(args: { + 'name': overlap.name, + 'time': '${overlap.startTime}-${overlap.endTime}', + }); + } + + String _formatError(Object e) { + final msg = e.toString(); + return msg.startsWith('Exception: ') ? msg.substring(11) : msg; + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/state/scheduled_activities_view_state.dart b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/state/scheduled_activities_view_state.dart new file mode 100644 index 00000000..1ea2d693 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/state/scheduled_activities_view_state.dart @@ -0,0 +1,14 @@ +import 'package:device_management/src/features/scheduled_activities/domain/entities/scheduled_activity_entity.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'scheduled_activities_view_state.freezed.dart'; + +@freezed +abstract class ScheduledActivitiesViewState + with _$ScheduledActivitiesViewState { + const factory ScheduledActivitiesViewState({ + @Default([]) List activities, + @Default(true) bool isLoading, + @Default('') String errorMessage, + }) = _ScheduledActivitiesViewState; +} diff --git a/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/state/scheduled_activities_view_state.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/state/scheduled_activities_view_state.freezed.dart new file mode 100644 index 00000000..79228772 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/state/scheduled_activities_view_state.freezed.dart @@ -0,0 +1,283 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'scheduled_activities_view_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$ScheduledActivitiesViewState { + + List get activities; bool get isLoading; String get errorMessage; +/// Create a copy of ScheduledActivitiesViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ScheduledActivitiesViewStateCopyWith get copyWith => _$ScheduledActivitiesViewStateCopyWithImpl(this as ScheduledActivitiesViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ScheduledActivitiesViewState&&const DeepCollectionEquality().equals(other.activities, activities)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(activities),isLoading,errorMessage); + +@override +String toString() { + return 'ScheduledActivitiesViewState(activities: $activities, isLoading: $isLoading, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class $ScheduledActivitiesViewStateCopyWith<$Res> { + factory $ScheduledActivitiesViewStateCopyWith(ScheduledActivitiesViewState value, $Res Function(ScheduledActivitiesViewState) _then) = _$ScheduledActivitiesViewStateCopyWithImpl; +@useResult +$Res call({ + List activities, bool isLoading, String errorMessage +}); + + + + +} +/// @nodoc +class _$ScheduledActivitiesViewStateCopyWithImpl<$Res> + implements $ScheduledActivitiesViewStateCopyWith<$Res> { + _$ScheduledActivitiesViewStateCopyWithImpl(this._self, this._then); + + final ScheduledActivitiesViewState _self; + final $Res Function(ScheduledActivitiesViewState) _then; + +/// Create a copy of ScheduledActivitiesViewState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? activities = null,Object? isLoading = null,Object? errorMessage = null,}) { + return _then(_self.copyWith( +activities: null == activities ? _self.activities : activities // ignore: cast_nullable_to_non_nullable +as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [ScheduledActivitiesViewState]. +extension ScheduledActivitiesViewStatePatterns on ScheduledActivitiesViewState { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _ScheduledActivitiesViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _ScheduledActivitiesViewState() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _ScheduledActivitiesViewState value) $default,){ +final _that = this; +switch (_that) { +case _ScheduledActivitiesViewState(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ScheduledActivitiesViewState value)? $default,){ +final _that = this; +switch (_that) { +case _ScheduledActivitiesViewState() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( List activities, bool isLoading, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _ScheduledActivitiesViewState() when $default != null: +return $default(_that.activities,_that.isLoading,_that.errorMessage);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( List activities, bool isLoading, String errorMessage) $default,) {final _that = this; +switch (_that) { +case _ScheduledActivitiesViewState(): +return $default(_that.activities,_that.isLoading,_that.errorMessage);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List activities, bool isLoading, String errorMessage)? $default,) {final _that = this; +switch (_that) { +case _ScheduledActivitiesViewState() when $default != null: +return $default(_that.activities,_that.isLoading,_that.errorMessage);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _ScheduledActivitiesViewState implements ScheduledActivitiesViewState { + const _ScheduledActivitiesViewState({final List activities = const [], this.isLoading = true, this.errorMessage = ''}): _activities = activities; + + + final List _activities; +@override@JsonKey() List get activities { + if (_activities is EqualUnmodifiableListView) return _activities; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_activities); +} + +@override@JsonKey() final bool isLoading; +@override@JsonKey() final String errorMessage; + +/// Create a copy of ScheduledActivitiesViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ScheduledActivitiesViewStateCopyWith<_ScheduledActivitiesViewState> get copyWith => __$ScheduledActivitiesViewStateCopyWithImpl<_ScheduledActivitiesViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ScheduledActivitiesViewState&&const DeepCollectionEquality().equals(other._activities, _activities)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_activities),isLoading,errorMessage); + +@override +String toString() { + return 'ScheduledActivitiesViewState(activities: $activities, isLoading: $isLoading, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class _$ScheduledActivitiesViewStateCopyWith<$Res> implements $ScheduledActivitiesViewStateCopyWith<$Res> { + factory _$ScheduledActivitiesViewStateCopyWith(_ScheduledActivitiesViewState value, $Res Function(_ScheduledActivitiesViewState) _then) = __$ScheduledActivitiesViewStateCopyWithImpl; +@override @useResult +$Res call({ + List activities, bool isLoading, String errorMessage +}); + + + + +} +/// @nodoc +class __$ScheduledActivitiesViewStateCopyWithImpl<$Res> + implements _$ScheduledActivitiesViewStateCopyWith<$Res> { + __$ScheduledActivitiesViewStateCopyWithImpl(this._self, this._then); + + final _ScheduledActivitiesViewState _self; + final $Res Function(_ScheduledActivitiesViewState) _then; + +/// Create a copy of ScheduledActivitiesViewState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? activities = null,Object? isLoading = null,Object? errorMessage = null,}) { + return _then(_ScheduledActivitiesViewState( +activities: null == activities ? _self._activities : activities // ignore: cast_nullable_to_non_nullable +as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/widgets/activity_form_sheet.dart b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/widgets/activity_form_sheet.dart new file mode 100644 index 00000000..6bfac262 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/widgets/activity_form_sheet.dart @@ -0,0 +1,356 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../domain/entities/scheduled_activity_entity.dart'; +import '../state/scheduled_activities_view_model.dart'; + +void showActivityFormSheet( + BuildContext context, { + ScheduledActivityEntity? activity, + int? weekDay, +}) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (_) => ActivityFormSheet(activity: activity, weekDay: weekDay), + ); +} + +class ActivityFormSheet extends ConsumerStatefulWidget { + final ScheduledActivityEntity? activity; + final int? weekDay; + + const ActivityFormSheet({super.key, this.activity, this.weekDay}); + + @override + ConsumerState createState() => _ActivityFormSheetState(); +} + +class _ActivityFormSheetState extends ConsumerState { + late final TextEditingController _nameController; + late int _selectedWeekDay; + late TimeOfDay _startTime; + late TimeOfDay _endTime; + bool _showStartPicker = false; + bool _showEndPicker = false; + + bool get _isEditing => widget.activity != null; + + bool get _isFormValid { + if (_nameController.text.trim().isEmpty) return false; + return _timeToMinutes(_startTime) < _timeToMinutes(_endTime); + } + + @override + void initState() { + super.initState(); + final activity = widget.activity; + _nameController = TextEditingController(text: activity?.name ?? ''); + _nameController.addListener(() => setState(() {})); + _selectedWeekDay = activity?.weekDay ?? widget.weekDay ?? 1; + + if (activity != null && activity.hasValidPeriod) { + _startTime = TimeOfDay( + hour: int.parse(activity.period.substring(0, 2)), + minute: int.parse(activity.period.substring(2, 4)), + ); + _endTime = TimeOfDay( + hour: int.parse(activity.period.substring(4, 6)), + minute: int.parse(activity.period.substring(6, 8)), + ); + } else { + _startTime = const TimeOfDay(hour: 8, minute: 0); + _endTime = const TimeOfDay(hour: 9, minute: 0); + } + } + + @override + void dispose() { + _nameController.dispose(); + super.dispose(); + } + + String _buildPeriod() { + return '${_startTime.hour.toString().padLeft(2, '0')}' + '${_startTime.minute.toString().padLeft(2, '0')}' + '${_endTime.hour.toString().padLeft(2, '0')}' + '${_endTime.minute.toString().padLeft(2, '0')}'; + } + + int _timeToMinutes(TimeOfDay time) => time.hour * 60 + time.minute; + + void _togglePicker({required bool isStart}) { + setState(() { + if (isStart) { + _showStartPicker = !_showStartPicker; + _showEndPicker = false; + } else { + _showEndPicker = !_showEndPicker; + _showStartPicker = false; + } + }); + } + + void _submit() { + if (!_isFormValid) return; + + final name = _nameController.text.trim(); + final period = _buildPeriod(); + final vm = ref.read(scheduledActivitiesViewModelProvider.notifier); + + if (_isEditing) { + vm.updateActivity( + activityId: widget.activity!.id, + weekDay: widget.activity!.weekDay, + name: name, + period: period, + ); + } else { + vm.createActivity(name: name, weekDay: _selectedWeekDay, period: period); + } + + Navigator.of(context).pop(); + } + + @override + Widget build(BuildContext context) { + final theme = ref.watch(themePortProvider); + final bottomInset = MediaQuery.of(context).viewInsets.bottom; + + return Padding( + padding: EdgeInsets.only(bottom: bottomInset), + child: Container( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundPrimary), + borderRadius: BorderRadius.vertical( + top: Radius.circular(SizeUtils.getByScreen(small: 20, big: 18)), + ), + ), + child: SafeArea( + child: SingleChildScrollView( + padding: EdgeInsets.all(SizeUtils.getByScreen(small: 22, big: 20)), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Center( + child: Container( + width: 40, + height: 4, + margin: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 16, big: 14), + ), + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(2), + ), + ), + ), + Text( + context.translate( + _isEditing + ? I18n.scheduledActivityEditTitle + : I18n.scheduledActivityNewTitle, + ), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 19), + fontWeight: FontWeight.bold, + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 20, big: 18)), + TextField( + controller: _nameController, + decoration: InputDecoration( + labelText: context.translate(I18n.name), + border: const OutlineInputBorder(), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 14)), + WeekDayChips.single( + selectedWeekDay: _isEditing + ? widget.activity!.weekDay + : _selectedWeekDay, + enabled: !_isEditing, + theme: theme, + onChanged: (value) => + setState(() => _selectedWeekDay = value), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 14)), + Row( + children: [ + Expanded( + child: _TimeSelector( + label: context.translate( + I18n.scheduledActivityStartTime, + ), + time: _startTime, + isExpanded: _showStartPicker, + onTap: () => _togglePicker(isStart: true), + theme: theme, + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 12, big: 10)), + Expanded( + child: _TimeSelector( + label: context.translate(I18n.scheduledActivityEndTime), + time: _endTime, + isExpanded: _showEndPicker, + onTap: () => _togglePicker(isStart: false), + theme: theme, + ), + ), + ], + ), + if (_showStartPicker) + _InlineTimePicker( + initialTime: _startTime, + onChanged: (time) => setState(() => _startTime = time), + ), + if (_showEndPicker) + _InlineTimePicker( + initialTime: _endTime, + onChanged: (time) => setState(() => _endTime = time), + ), + SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)), + SizedBox( + height: SizeUtils.getByScreen(small: 48, big: 46), + child: ElevatedButton( + onPressed: _isFormValid ? _submit : null, + style: ElevatedButton.styleFrom( + backgroundColor: theme.getColorFor( + ThemeCode.legacyPrimary, + ), + disabledBackgroundColor: Colors.grey[300], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + SizeUtils.getByScreen(small: 12, big: 10), + ), + ), + ), + child: Text( + context.translate(I18n.save), + style: TextStyle( + color: _isFormValid ? Colors.white : Colors.grey, + fontSize: SizeUtils.getByScreen(small: 16, big: 15), + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} + +class _TimeSelector extends StatelessWidget { + final String label; + final TimeOfDay time; + final bool isExpanded; + final VoidCallback onTap; + final ThemePort theme; + + const _TimeSelector({ + required this.label, + required this.time, + required this.isExpanded, + required this.onTap, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 12, big: 10), + vertical: SizeUtils.getByScreen(small: 14, big: 12), + ), + decoration: BoxDecoration( + border: Border.all( + color: isExpanded + ? theme.getColorFor(ThemeCode.legacyPrimary) + : Colors.grey, + width: isExpanded ? 2 : 1, + ), + borderRadius: BorderRadius.circular(4), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + time.format(context), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 16, big: 15), + fontWeight: FontWeight.w500, + ), + ), + Icon( + isExpanded + ? Icons.keyboard_arrow_up + : Icons.keyboard_arrow_down, + size: SizeUtils.getByScreen(small: 20, big: 18), + color: theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.5), + ), + ], + ), + ], + ), + ), + ); + } +} + +class _InlineTimePicker extends StatelessWidget { + final TimeOfDay initialTime; + final ValueChanged onChanged; + + const _InlineTimePicker({required this.initialTime, required this.onChanged}); + + @override + Widget build(BuildContext context) { + return Container( + height: SizeUtils.getByScreen(small: 180, big: 160), + margin: EdgeInsets.only(top: SizeUtils.getByScreen(small: 8, big: 6)), + child: CupertinoDatePicker( + mode: CupertinoDatePickerMode.time, + use24hFormat: true, + initialDateTime: DateTime( + 0, + 1, + 1, + initialTime.hour, + initialTime.minute, + ), + onDateTimeChanged: (dateTime) { + onChanged(TimeOfDay(hour: dateTime.hour, minute: dateTime.minute)); + }, + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/widgets/confirm_delete_activity_dialog.dart b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/widgets/confirm_delete_activity_dialog.dart new file mode 100644 index 00000000..a87abc94 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/widgets/confirm_delete_activity_dialog.dart @@ -0,0 +1,77 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../domain/entities/scheduled_activity_entity.dart'; +import '../state/scheduled_activities_view_model.dart'; + +class ConfirmDeleteActivityDialog extends ConsumerWidget { + final ScheduledActivityEntity activity; + + const ConfirmDeleteActivityDialog({super.key, required this.activity}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.read(themePortProvider); + + return Container( + padding: SizeUtils.getByScreen( + small: const EdgeInsets.symmetric(horizontal: 32, vertical: 30), + big: const EdgeInsets.symmetric(horizontal: 30, vertical: 28), + ), + width: SizeUtils.getByScreen(small: 360, big: 350), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundPrimary), + borderRadius: BorderRadius.circular( + SizeUtils.getByScreen(small: 16, big: 14), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + I18n.scheduledActivityDeleteMessage.tr( + args: {'name': activity.name}, + ), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 19, big: 18), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 28, big: 27)), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: PrimaryButton( + onPressed: () => Navigator.pop(context), + text: context.translate(I18n.cancel), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: SizeUtils.getByScreen(small: 38, big: 36), + radius: SizeUtils.getByScreen(small: 32, big: 34), + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 4, big: 16)), + Expanded( + child: PrimaryButton( + onPressed: () { + Navigator.pop(context); + ref + .read(scheduledActivitiesViewModelProvider.notifier) + .deleteActivity(activity.id); + }, + text: context.translate(I18n.delete), + color: const Color(0xFFFF5D52), + height: SizeUtils.getByScreen(small: 38, big: 36), + radius: SizeUtils.getByScreen(small: 32, big: 34), + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/widgets/day_timeline.dart b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/widgets/day_timeline.dart new file mode 100644 index 00000000..21e9a2af --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/presentation/widgets/day_timeline.dart @@ -0,0 +1,238 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../../domain/entities/scheduled_activity_entity.dart'; +import 'activity_form_sheet.dart'; +import 'confirm_delete_activity_dialog.dart'; + +class DayTimeline extends ConsumerWidget { + final List activities; + + const DayTimeline({super.key, required this.activities}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + if (activities.isEmpty) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + SFIcons.calendarCircle, + size: SizeUtils.getByScreen(small: 48, big: 44), + color: theme.getColorFor(ThemeCode.textSecondary), + ), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), + Text( + context.translate(I18n.scheduledActivityEmpty), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 14), + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 6, big: 4)), + Text( + context.translate(I18n.scheduledActivityEmptyHint), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ), + ], + ), + ); + } + + return ListView.builder( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + vertical: SizeUtils.getByScreen(small: 12, big: 10), + ), + itemCount: activities.length, + itemBuilder: (context, index) { + final activity = activities[index]; + final isLast = index == activities.length - 1; + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + + return IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _TimeLabels( + startTime: activity.startTime, + endTime: activity.endTime, + theme: theme, + ), + _TimelineDotAndLine( + isLast: isLast, + color: primaryColor, + ), + SizedBox(width: SizeUtils.getByScreen(small: 10, big: 8)), + Expanded( + child: _ActivityTimelineCard( + activity: activity, + theme: theme, + ), + ), + ], + ), + ); + }, + ); + } +} + +class _TimeLabels extends StatelessWidget { + final String startTime; + final String endTime; + final ThemePort theme; + + const _TimeLabels({ + required this.startTime, + required this.endTime, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + final style = TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11), + fontWeight: FontWeight.w500, + color: theme.getColorFor(ThemeCode.textPrimary), + ); + + return SizedBox( + width: SizeUtils.getByScreen(small: 42, big: 38), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + SizedBox(height: SizeUtils.getByScreen(small: 10, big: 8)), + Text(startTime, style: style), + const Spacer(), + Padding( + padding: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 14, big: 12), + ), + child: Text( + endTime, + style: style.copyWith( + color: theme.getColorFor(ThemeCode.textPrimary).withValues(alpha: 0.5), + ), + ), + ), + ], + ), + ); + } +} + +class _TimelineDotAndLine extends StatelessWidget { + final bool isLast; + final Color color; + + const _TimelineDotAndLine({required this.isLast, required this.color}); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: SizeUtils.getByScreen(small: 20, big: 18), + child: Column( + children: [ + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), + Container( + width: SizeUtils.getByScreen(small: 12, big: 10), + height: SizeUtils.getByScreen(small: 12, big: 10), + decoration: BoxDecoration(shape: BoxShape.circle, color: color), + ), + if (!isLast) + Expanded( + child: Container( + width: 2, + color: color.withValues(alpha: 0.3), + ), + ), + ], + ), + ); + } +} + +class _ActivityTimelineCard extends StatelessWidget { + final ScheduledActivityEntity activity; + final ThemePort theme; + + const _ActivityTimelineCard({ + required this.activity, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 10, big: 8), + ), + padding: SizeUtils.getByScreen( + small: const EdgeInsets.fromLTRB(14, 10, 6, 10), + big: const EdgeInsets.fromLTRB(12, 8, 4, 8), + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + SizeUtils.getByScreen(small: 12, big: 10), + ), + color: theme.getColorFor(ThemeCode.backgroundSecondary), + ), + child: Row( + children: [ + Expanded( + child: Text( + activity.name, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 14), + fontWeight: FontWeight.w600, + ), + ), + ), + IconButton( + onPressed: () => + showActivityFormSheet(context, activity: activity), + icon: Icon( + Icons.edit_outlined, + color: theme.getColorFor(ThemeCode.legacyPrimary), + size: SizeUtils.getByScreen(small: 20, big: 18), + ), + constraints: const BoxConstraints(), + padding: EdgeInsets.all( + SizeUtils.getByScreen(small: 8, big: 6), + ), + ), + IconButton( + onPressed: () { + showDialog( + context: context, + builder: (_) => Dialog( + backgroundColor: Colors.transparent, + child: ConfirmDeleteActivityDialog(activity: activity), + ), + ); + }, + icon: Icon( + Icons.delete_outlined, + color: const Color(0xFFFF5D52), + size: SizeUtils.getByScreen(small: 20, big: 18), + ), + constraints: const BoxConstraints(), + padding: EdgeInsets.all( + SizeUtils.getByScreen(small: 8, big: 6), + ), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/scheduled_activities_builder.dart b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/scheduled_activities_builder.dart new file mode 100644 index 00000000..02f4ff7f --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/scheduled_activities/scheduled_activities_builder.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:go_router/go_router.dart'; +import 'package:navigation/navigation.dart'; + +import 'presentation/scheduled_activities_screen.dart'; + +class ScheduledActivitiesBuilder { + const ScheduledActivitiesBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: ScheduledActivitiesScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/device_management/pubspec.lock b/modules/legacy/modules/device_management/pubspec.lock index 21251596..355eed13 100644 --- a/modules/legacy/modules/device_management/pubspec.lock +++ b/modules/legacy/modules/device_management/pubspec.lock @@ -335,7 +335,7 @@ packages: source: hosted version: "1.1.1" fl_chart: - dependency: transitive + dependency: "direct main" description: name: fl_chart sha256: "7ca9a40f4eb85949190e54087be8b4d6ac09dc4c54238d782a34cf1f7c011de9" @@ -347,6 +347,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_contacts: + dependency: "direct main" + description: + name: flutter_contacts + sha256: "388d32cd33f16640ee169570128c933b45f3259bddbfae7a100bb49e5ffea9ae" + url: "https://pub.dev" + source: hosted + version: "1.1.9+2" flutter_lints: dependency: "direct dev" description: @@ -1223,7 +1231,7 @@ packages: source: path version: "0.0.1" uuid: - dependency: transitive + dependency: "direct main" description: name: uuid sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" diff --git a/modules/legacy/modules/device_management/pubspec.yaml b/modules/legacy/modules/device_management/pubspec.yaml index 72020dc4..febe3c21 100644 --- a/modules/legacy/modules/device_management/pubspec.yaml +++ b/modules/legacy/modules/device_management/pubspec.yaml @@ -53,6 +53,9 @@ dependencies: json_annotation: ^4.9.0 json_serializable: ^6.11.2 url_launcher: ^6.3.2 + uuid: ^4.5.1 + flutter_contacts: ^1.1.9+2 + fl_chart: ^1.1.1 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/device_setup_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/device_setup_screen.dart index 5a7235b0..6b90acf6 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/device_setup_screen.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/device_setup_screen.dart @@ -62,7 +62,7 @@ class LegacyDeviceSetupScreen extends ConsumerWidget { else IconButton( onPressed: vm.back, - icon: const Icon(Icons.arrow_back_ios_new_rounded), + icon: Icon(Icons.adaptive.arrow_back), color: theme.getColorFor(ThemeCode.textPrimary), tooltip: MaterialLocalizations.of( context, @@ -74,7 +74,7 @@ class LegacyDeviceSetupScreen extends ConsumerWidget { : StepIndicator( total: LegacyAddKidStep.mainStepCount, current: state.step.mainStepIndex + 1, - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), ), const SizedBox(width: 48), diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/intro_step.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/intro_step.dart index 77c928fa..64ed419e 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/intro_step.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/intro_step.dart @@ -31,7 +31,7 @@ class LegacyIntroStepScreen extends ConsumerWidget { context.translate(I18n.deviceSetup_intro_step_1), context.translate(I18n.deviceSetup_intro_step_2), ], - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), ], ); diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/success_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/success_screen.dart index bc0b3b0a..191f8ad6 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/success_screen.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/success_screen.dart @@ -30,7 +30,7 @@ class LegacySuccessScreen extends ConsumerWidget { children: [ Icon( Icons.check, - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), size: 50, ), const SizedBox(height: 20), diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/flow_footer.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/flow_footer.dart index 6b977ef1..b0c85579 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/flow_footer.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/flow_footer.dart @@ -34,7 +34,7 @@ class LegacyFlowFooter extends StatelessWidget { PrimaryButton( text: primaryText, onPressed: onPrimary, - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), if (secondaryText != null && onSecondary != null) ...[ const SizedBox(height: 10), diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart index 39561826..a2c84076 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart @@ -100,7 +100,7 @@ class LegacyRequestLinkPhoneScreen extends ConsumerWidget { } }, text: context.translate(I18n.next), - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), ], ), diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart index 9190097a..0c6c8d5b 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart @@ -89,7 +89,7 @@ class LegacyVerifyLinkPhoneCodeScreen extends ConsumerWidget { } }, text: context.translate(I18n.enter), - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), const SizedBox(height: 24), Text( diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/loading_google_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/loading_google_screen.dart index 46324e01..c969cce4 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/loading_google_screen.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/loading_google_screen.dart @@ -1,5 +1,6 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; class LegacyLoadingGoogleScreen extends StatelessWidget { const LegacyLoadingGoogleScreen({super.key}); @@ -14,11 +15,11 @@ class LegacyLoadingGoogleScreen extends StatelessWidget { children: [ Spacer(flex: 8), Text( - "Continuar con Google", + context.translate(I18n.continueWithGoogle), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30), ), AppLoadingIndicator(), - Text("Redirigiendo a Google"), + Text(context.translate(I18n.redirectingToGoogle)), Spacer(flex: 10), ], ), diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/login_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/login_screen.dart index 860ecc41..0a720aff 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/login_screen.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/login_screen.dart @@ -105,7 +105,7 @@ class _Header extends StatelessWidget { children: [ Icon( Icons.check, - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), size: 54, ), Text( @@ -216,7 +216,7 @@ class _SignInSection extends ConsumerWidget { PrimaryButton( onPressed: isLoading ? () {} : onSignIn, text: context.translate(I18n.signIn), - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), leading: isLoading ? const SizedBox( height: 18, diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_model.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_model.dart index f4cb3099..6f62f7d1 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_model.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_model.dart @@ -2,11 +2,11 @@ import 'dart:async'; import 'package:legacy_auth/src/core/domain/repositories/login_repository.dart'; import 'package:legacy_auth/src/core/providers/login_repository_provider.dart'; -import 'package:legacy_shared/src/utils/dio_error_mapper.dart'; import 'package:legacy_auth/src/features/login/presentation/mixins/login_form_validation.dart'; import 'package:legacy_auth/src/features/login/presentation/state/login_view_state.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; import 'package:sf_shared/sf_shared.dart'; final legacyLoginViewModelProvider = @@ -58,8 +58,9 @@ class LegacyLoginViewModel extends Notifier state = state.copyWith( password: value, errorMessage: '', - passwordError: - state.showErrors ? validatePassword(value) : state.passwordError, + passwordError: state.showErrors + ? validatePassword(value) + : state.passwordError, ); } @@ -170,18 +171,15 @@ class LegacyLoginViewModel extends Notifier void _startResendCooldown() { _cooldownTimer?.cancel(); state = state.copyWith(resendCooldown: resendCooldownSeconds); - _cooldownTimer = Timer.periodic( - const Duration(seconds: 1), - (_) { - if (!ref.mounted) { - _cooldownTimer?.cancel(); - return; - } - final next = state.resendCooldown - 1; - state = state.copyWith(resendCooldown: next); - if (next <= 0) _cooldownTimer?.cancel(); - }, - ); + _cooldownTimer = Timer.periodic(const Duration(seconds: 1), (_) { + if (!ref.mounted) { + _cooldownTimer?.cancel(); + return; + } + final next = state.resendCooldown - 1; + state = state.copyWith(resendCooldown: next); + if (next <= 0) _cooldownTimer?.cancel(); + }); } Future submitTwoFACode() async { diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/two_factor_bottom_sheet.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/two_factor_bottom_sheet.dart index 68e60e07..f983a53b 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/two_factor_bottom_sheet.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/two_factor_bottom_sheet.dart @@ -96,7 +96,7 @@ class LegacyTwoFactorBottomSheetView extends StatelessWidget { ? () {} : () => unawaited(onVerify()), text: verifyText, - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), leading: isOtpLoading ? const SizedBox( height: 18, diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_screen.dart index 4a9e1dc9..6f552a2d 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_screen.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_screen.dart @@ -24,9 +24,11 @@ class LegacyOnboardingScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); final state = ref.watch(legacyOnBoardingViewModelProvider); final viewModel = ref.read(legacyOnBoardingViewModelProvider.notifier); final pageController = ref.watch(legacyOnboardingPageControllerProvider); + final legacyColor = theme.getColorFor(ThemeCode.legacyPrimary); final isLast = state.cardIndex >= onboardingPages.length - 1; @@ -65,7 +67,7 @@ class LegacyOnboardingScreen extends ConsumerWidget { StepIndicator( current: state.cardIndex + 1, total: onboardingPages.length, - color: Color.fromRGBO(88, 142, 165, 1), + color: legacyColor, ), const SizedBox(height: 38), Container( @@ -75,19 +77,19 @@ class LegacyOnboardingScreen extends ConsumerWidget { onPressed: goToNext, style: TextButton.styleFrom( backgroundColor: isLast - ? const Color.fromRGBO(88, 142, 165, 1) - : const Color.fromRGBO(255, 255, 255, 1), + ? legacyColor + : Colors.white, foregroundColor: isLast - ? const Color.fromRGBO(255, 255, 255, 1) - : const Color.fromRGBO(88, 142, 165, 1), + ? Colors.white + : legacyColor, padding: const EdgeInsets.symmetric( vertical: 16, horizontal: 24, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(18), - side: const BorderSide( - color: Color.fromRGBO(88, 142, 165, 1), + side: BorderSide( + color: legacyColor, width: 3, ), ), @@ -115,7 +117,7 @@ class LegacyOnboardingScreen extends ConsumerWidget { child: Text( context.translate(I18n.skip), style: AppFonts.stolzlStyle( - color: Color.fromRGBO(88, 142, 165, 1), + color: legacyColor, decoration: TextDecoration.underline, weight: FontWeight.w600, size: 18, diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/new_password/new_password_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/new_password/new_password_screen.dart index 88bed7fd..a823c178 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/new_password/new_password_screen.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/new_password/new_password_screen.dart @@ -87,7 +87,7 @@ class LegacyNewPasswordScreen extends ConsumerWidget { Icons.check, color: theme.getColorFor( viewState.securityChecks['min']! - ? ThemeCode.buttonPrimary + ? ThemeCode.legacyPrimary : ThemeCode.buttonSecondary, ), ), @@ -111,7 +111,7 @@ class LegacyNewPasswordScreen extends ConsumerWidget { Icons.check, color: theme.getColorFor( viewState.securityChecks['capital']! - ? ThemeCode.buttonPrimary + ? ThemeCode.legacyPrimary : ThemeCode.buttonSecondary, ), ), @@ -135,7 +135,7 @@ class LegacyNewPasswordScreen extends ConsumerWidget { Icons.check, color: theme.getColorFor( viewState.securityChecks['number']! - ? ThemeCode.buttonPrimary + ? ThemeCode.legacyPrimary : ThemeCode.buttonSecondary, ), ), @@ -159,7 +159,7 @@ class LegacyNewPasswordScreen extends ConsumerWidget { Icons.check, color: theme.getColorFor( viewState.securityChecks['special']! - ? ThemeCode.buttonPrimary + ? ThemeCode.legacyPrimary : ThemeCode.buttonSecondary, ), ), @@ -237,7 +237,7 @@ class LegacyNewPasswordScreen extends ConsumerWidget { } }, text: context.translate(I18n.accept), - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), ], ), diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/sent/sent_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/sent/sent_screen.dart index 46f1937f..d505dbc9 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/sent/sent_screen.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/sent/sent_screen.dart @@ -45,7 +45,7 @@ class LegacySentScreen extends ConsumerWidget { children: [ Icon( Icons.check, - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), SizedBox( width: SizeUtils.getByScreen(small: 10, big: 10, xl: 6), diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/account_created_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/account_created_screen.dart index 981aa761..04d27651 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/account_created_screen.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/account_created_screen.dart @@ -29,7 +29,7 @@ class LegacyAccountCreatedScreen extends ConsumerWidget { const Spacer(flex: 10), Icon( Icons.check, - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), size: 50, ), const SizedBox(height: 20), @@ -80,7 +80,7 @@ class LegacyAccountCreatedScreen extends ConsumerWidget { PrimaryButton( onPressed: () => navigationContract.goTo(AppRoutes.login), text: context.translate(I18n.accountCreatedContinue), - color: Color.fromRGBO(88, 142, 165, 1), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), const Spacer(flex: 8), ], diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_personal_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_personal_screen.dart index d8bbe6d7..6015a9ad 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_personal_screen.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_personal_screen.dart @@ -144,7 +144,7 @@ class LegacySignupPersonalScreen extends StatelessWidget { ), checkboxScaleFactor: 1.5, contentPadding: EdgeInsets.zero, - activeColor: theme.getColorFor(ThemeCode.buttonPrimary), + activeColor: theme.getColorFor(ThemeCode.legacyPrimary), controlAffinity: ListTileControlAffinity.leading, ), ], diff --git a/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/form_step_layout.dart b/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/form_step_layout.dart index 84439b8f..6c95d026 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/form_step_layout.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/form_step_layout.dart @@ -1,6 +1,7 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; class LegacyFormStepLayout extends ConsumerWidget { final int currentStep; @@ -46,7 +47,7 @@ class LegacyFormStepLayout extends ConsumerWidget { child: StepIndicator( total: numSteps, current: currentStep, - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), ), SizedBox(height: 16), @@ -78,6 +79,7 @@ class LegacyFormStepLayout extends ConsumerWidget { SizedBox(height: 16), if (footer == null) navigationButtons( + context, currentStep, numSteps, nextStep, @@ -94,6 +96,7 @@ class LegacyFormStepLayout extends ConsumerWidget { } Widget navigationButtons( + BuildContext context, int currentStep, int numSteps, VoidCallback nextStep, @@ -103,8 +106,8 @@ class LegacyFormStepLayout extends ConsumerWidget { if (currentStep == numSteps) { return PrimaryButton( onPressed: nextStep, - text: "Continuar", - color: theme.getColorFor(ThemeCode.buttonPrimary), + text: context.translate(I18n.continueKey), + color: theme.getColorFor(ThemeCode.legacyPrimary), ); } else { return Row( @@ -113,14 +116,14 @@ class LegacyFormStepLayout extends ConsumerWidget { Expanded( child: SecondaryButton( onPressed: previousStep, - text: "Atrás", + text: context.translate(I18n.back), size: 16, ), ), Expanded( child: PrimaryButton( onPressed: nextStep, - text: "Siguiente", + text: context.translate(I18n.next), size: 16, color: theme.getColorFor(ThemeCode.buttonSecondary), ), diff --git a/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/sign_up_layout.dart b/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/sign_up_layout.dart index 69809f91..6390052e 100644 --- a/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/sign_up_layout.dart +++ b/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/sign_up_layout.dart @@ -1,5 +1,6 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; class LegacySignUpLayout extends StatelessWidget { final ThemePort theme; @@ -57,7 +58,7 @@ class LegacySignUpLayout extends StatelessWidget { child: StepIndicator( total: numSteps, current: currentStep, - color: theme.getColorFor(ThemeCode.buttonPrimary), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), ), const SizedBox(height: 8), @@ -96,16 +97,16 @@ class LegacySignUpLayout extends StatelessWidget { Expanded( child: SecondaryButton( onPressed: onBackPressed, - text: "Atrás", + text: context.translate(I18n.back), size: 16, ), ), Expanded( child: PrimaryButton( onPressed: onNextPressed, - text: "Siguiente", + text: context.translate(I18n.next), size: 16, - color: Color.fromRGBO(88, 142, 165, 1), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), ), ], diff --git a/modules/legacy/modules/legacy_auth/pubspec_overrides.yaml b/modules/legacy/modules/legacy_auth/pubspec_overrides.yaml index 299c68f5..529a0843 100644 --- a/modules/legacy/modules/legacy_auth/pubspec_overrides.yaml +++ b/modules/legacy/modules/legacy_auth/pubspec_overrides.yaml @@ -14,7 +14,7 @@ dependency_overrides: home: path: ../../../home legacy_shared: - path: ..\\..\\packages\\legacy_shared + path: ../../packages/legacy_shared navigation: path: ../../../../packages/navigation notifications: diff --git a/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_screen.dart b/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_screen.dart index 0b051380..0709e0a7 100644 --- a/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_screen.dart +++ b/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_screen.dart @@ -1,17 +1,10 @@ -import 'package:legacy_dashboard_shell/src/presentation/legacy_main_shell_view_model.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; -import 'package:legacy_dashboard_shell/src/presentation/legacy_main_shell_view_state.dart'; import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; -final mainShellViewModelProvider = - NotifierProvider.autoDispose( - () => LegacyMainShellViewModel(), - ); - class LegacyDashboardScreen extends ConsumerWidget { final NavigationContract navigationContract; final StatefulNavigationShell navigationShell; @@ -25,16 +18,13 @@ class LegacyDashboardScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final theme = ref.watch(themePortProvider); - final viewState = ref.watch(mainShellViewModelProvider); - final viewModel = ref.read(mainShellViewModelProvider.notifier); return Scaffold( body: navigationShell, bottomNavigationBar: NavigationBar( backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), - selectedIndex: viewState.selectedIndex, + selectedIndex: navigationShell.currentIndex, onDestinationSelected: (index) { - viewModel.onTabChanged(index); navigationShell.goBranch(index); }, destinations: [ diff --git a/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_view_model.dart b/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_view_model.dart deleted file mode 100644 index 4a92901a..00000000 --- a/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_view_model.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:legacy_dashboard_shell/src/presentation/legacy_main_shell_view_state.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -class LegacyMainShellViewModel extends Notifier { - @override - LegacyMainShellViewState build() { - return LegacyMainShellViewState(); - } - - void onTabChanged(int index) { - state = state.copyWith(selectedIndex: index); - } -} diff --git a/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_view_state.dart b/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_view_state.dart deleted file mode 100644 index c258052d..00000000 --- a/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_view_state.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; -part 'legacy_main_shell_view_state.freezed.dart'; - -@freezed -abstract class LegacyMainShellViewState with _$LegacyMainShellViewState { - const factory LegacyMainShellViewState({ - @Default(0) int selectedIndex, - @Default(false) bool isLoading, - @Default(false) bool isComplete, - String? error, - }) = _LegacyMainShellViewState; - - -} diff --git a/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_view_state.freezed.dart b/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_view_state.freezed.dart deleted file mode 100644 index 62c23135..00000000 --- a/modules/legacy/modules/legacy_dashboard_shell/lib/src/presentation/legacy_main_shell_view_state.freezed.dart +++ /dev/null @@ -1,280 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND -// coverage:ignore-file -// ignore_for_file: type=lint -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark - -part of 'legacy_main_shell_view_state.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -// dart format off -T _$identity(T value) => value; -/// @nodoc -mixin _$LegacyMainShellViewState { - - int get selectedIndex; bool get isLoading; bool get isComplete; String? get error; -/// Create a copy of LegacyMainShellViewState -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$LegacyMainShellViewStateCopyWith get copyWith => _$LegacyMainShellViewStateCopyWithImpl(this as LegacyMainShellViewState, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyMainShellViewState&&(identical(other.selectedIndex, selectedIndex) || other.selectedIndex == selectedIndex)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.error, error) || other.error == error)); -} - - -@override -int get hashCode => Object.hash(runtimeType,selectedIndex,isLoading,isComplete,error); - -@override -String toString() { - return 'LegacyMainShellViewState(selectedIndex: $selectedIndex, isLoading: $isLoading, isComplete: $isComplete, error: $error)'; -} - - -} - -/// @nodoc -abstract mixin class $LegacyMainShellViewStateCopyWith<$Res> { - factory $LegacyMainShellViewStateCopyWith(LegacyMainShellViewState value, $Res Function(LegacyMainShellViewState) _then) = _$LegacyMainShellViewStateCopyWithImpl; -@useResult -$Res call({ - int selectedIndex, bool isLoading, bool isComplete, String? error -}); - - - - -} -/// @nodoc -class _$LegacyMainShellViewStateCopyWithImpl<$Res> - implements $LegacyMainShellViewStateCopyWith<$Res> { - _$LegacyMainShellViewStateCopyWithImpl(this._self, this._then); - - final LegacyMainShellViewState _self; - final $Res Function(LegacyMainShellViewState) _then; - -/// Create a copy of LegacyMainShellViewState -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? selectedIndex = null,Object? isLoading = null,Object? isComplete = null,Object? error = freezed,}) { - return _then(_self.copyWith( -selectedIndex: null == selectedIndex ? _self.selectedIndex : selectedIndex // ignore: cast_nullable_to_non_nullable -as int,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable -as bool,isComplete: null == isComplete ? _self.isComplete : isComplete // ignore: cast_nullable_to_non_nullable -as bool,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable -as String?, - )); -} - -} - - -/// Adds pattern-matching-related methods to [LegacyMainShellViewState]. -extension LegacyMainShellViewStatePatterns on LegacyMainShellViewState { -/// A variant of `map` that fallback to returning `orElse`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeMap(TResult Function( _LegacyMainShellViewState value)? $default,{required TResult orElse(),}){ -final _that = this; -switch (_that) { -case _LegacyMainShellViewState() when $default != null: -return $default(_that);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// Callbacks receives the raw object, upcasted. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case final Subclass2 value: -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult map(TResult Function( _LegacyMainShellViewState value) $default,){ -final _that = this; -switch (_that) { -case _LegacyMainShellViewState(): -return $default(_that);case _: - throw StateError('Unexpected subclass'); - -} -} -/// A variant of `map` that fallback to returning `null`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? mapOrNull(TResult? Function( _LegacyMainShellViewState value)? $default,){ -final _that = this; -switch (_that) { -case _LegacyMainShellViewState() when $default != null: -return $default(_that);case _: - return null; - -} -} -/// A variant of `when` that fallback to an `orElse` callback. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeWhen(TResult Function( int selectedIndex, bool isLoading, bool isComplete, String? error)? $default,{required TResult orElse(),}) {final _that = this; -switch (_that) { -case _LegacyMainShellViewState() when $default != null: -return $default(_that.selectedIndex,_that.isLoading,_that.isComplete,_that.error);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// As opposed to `map`, this offers destructuring. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case Subclass2(:final field2): -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult when(TResult Function( int selectedIndex, bool isLoading, bool isComplete, String? error) $default,) {final _that = this; -switch (_that) { -case _LegacyMainShellViewState(): -return $default(_that.selectedIndex,_that.isLoading,_that.isComplete,_that.error);case _: - throw StateError('Unexpected subclass'); - -} -} -/// A variant of `when` that fallback to returning `null` -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? whenOrNull(TResult? Function( int selectedIndex, bool isLoading, bool isComplete, String? error)? $default,) {final _that = this; -switch (_that) { -case _LegacyMainShellViewState() when $default != null: -return $default(_that.selectedIndex,_that.isLoading,_that.isComplete,_that.error);case _: - return null; - -} -} - -} - -/// @nodoc - - -class _LegacyMainShellViewState implements LegacyMainShellViewState { - const _LegacyMainShellViewState({this.selectedIndex = 0, this.isLoading = false, this.isComplete = false, this.error}); - - -@override@JsonKey() final int selectedIndex; -@override@JsonKey() final bool isLoading; -@override@JsonKey() final bool isComplete; -@override final String? error; - -/// Create a copy of LegacyMainShellViewState -/// with the given fields replaced by the non-null parameter values. -@override @JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -_$LegacyMainShellViewStateCopyWith<_LegacyMainShellViewState> get copyWith => __$LegacyMainShellViewStateCopyWithImpl<_LegacyMainShellViewState>(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyMainShellViewState&&(identical(other.selectedIndex, selectedIndex) || other.selectedIndex == selectedIndex)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.error, error) || other.error == error)); -} - - -@override -int get hashCode => Object.hash(runtimeType,selectedIndex,isLoading,isComplete,error); - -@override -String toString() { - return 'LegacyMainShellViewState(selectedIndex: $selectedIndex, isLoading: $isLoading, isComplete: $isComplete, error: $error)'; -} - - -} - -/// @nodoc -abstract mixin class _$LegacyMainShellViewStateCopyWith<$Res> implements $LegacyMainShellViewStateCopyWith<$Res> { - factory _$LegacyMainShellViewStateCopyWith(_LegacyMainShellViewState value, $Res Function(_LegacyMainShellViewState) _then) = __$LegacyMainShellViewStateCopyWithImpl; -@override @useResult -$Res call({ - int selectedIndex, bool isLoading, bool isComplete, String? error -}); - - - - -} -/// @nodoc -class __$LegacyMainShellViewStateCopyWithImpl<$Res> - implements _$LegacyMainShellViewStateCopyWith<$Res> { - __$LegacyMainShellViewStateCopyWithImpl(this._self, this._then); - - final _LegacyMainShellViewState _self; - final $Res Function(_LegacyMainShellViewState) _then; - -/// Create a copy of LegacyMainShellViewState -/// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? selectedIndex = null,Object? isLoading = null,Object? isComplete = null,Object? error = freezed,}) { - return _then(_LegacyMainShellViewState( -selectedIndex: null == selectedIndex ? _self.selectedIndex : selectedIndex // ignore: cast_nullable_to_non_nullable -as int,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable -as bool,isComplete: null == isComplete ? _self.isComplete : isComplete // ignore: cast_nullable_to_non_nullable -as bool,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable -as String?, - )); -} - - -} - -// dart format on diff --git a/modules/legacy/modules/location/lib/src/features/location/presentation/location_screen.dart b/modules/legacy/modules/location/lib/src/features/location/presentation/location_screen.dart index 9268529b..16d598d1 100644 --- a/modules/legacy/modules/location/lib/src/features/location/presentation/location_screen.dart +++ b/modules/legacy/modules/location/lib/src/features/location/presentation/location_screen.dart @@ -22,32 +22,22 @@ class LocationScreen extends ConsumerWidget { return Scaffold( backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), - body: SafeArea( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: EdgeInsets.symmetric( - horizontal: 14, - vertical: SizeUtils.getByScreen(small: 12, big: 14), - ), - child: Text( - context.translate(I18n.watchesOnMap), - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 20, big: 19), - fontWeight: FontWeight.bold, - color: theme.getColorFor(ThemeCode.legacyPrimary), - ), - ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.symmetric( + horizontal: 14, + vertical: SizeUtils.getByScreen(small: 12, big: 14), ), - Expanded( - child: DeviceMap( - selectedPosition: state.selectedPosition, - selectedDevice: state.selectedDevice, - ), + ), + Expanded( + child: DeviceMap( + selectedPosition: state.selectedPosition, + selectedDevice: state.selectedDevice, ), - ], - ), + ), + ], ), ); } diff --git a/modules/legacy/modules/settings/lib/settings.dart b/modules/legacy/modules/settings/lib/settings.dart new file mode 100644 index 00000000..5f4b6d99 --- /dev/null +++ b/modules/legacy/modules/settings/lib/settings.dart @@ -0,0 +1,16 @@ +export 'src/features/settings/settings_builder.dart'; +export 'src/features/alarm/alarm_builder.dart'; +export 'src/features/app_store/app_store_builder.dart'; +export 'src/features/battery/battery_builder.dart'; +export 'src/features/block_phone/block_phone_builder.dart'; +export 'src/features/disable_functions/disable_functions_builder.dart'; +export 'src/features/language/language_builder.dart'; +export 'src/features/legacy_notifications/legacy_notifications_builder.dart'; +export 'src/features/remote_management/remote_management_builder.dart'; +export 'src/features/remote_on_off/remote_on_off_builder.dart'; +export 'src/features/sms_alert/sms_alert_builder.dart'; +export 'src/features/sos_contacts/sos_contacts_builder.dart'; +export 'src/features/sound/sound_builder.dart'; +export 'src/features/sync_clock/sync_clock_builder.dart'; +export 'src/features/timezone/timezone_builder.dart'; +export 'src/features/wifi_settings/wifi_settings_builder.dart'; diff --git a/modules/legacy/modules/settings/lib/src/core/data/datasources/alarm_remote_datasource.dart b/modules/legacy/modules/settings/lib/src/core/data/datasources/alarm_remote_datasource.dart new file mode 100644 index 00000000..e308854d --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/datasources/alarm_remote_datasource.dart @@ -0,0 +1,13 @@ +import 'package:settings/src/core/data/models/create_alarm_request_model.dart'; +import 'package:settings/src/core/data/models/get_alarms_response_model.dart'; +import 'package:settings/src/core/data/models/update_alarm_request_model.dart'; + +abstract class AlarmRemoteDatasource { + Future getAlarms({required String deviceId}); + Future createAlarm({required CreateAlarmRequestModel request}); + Future updateAlarm({ + required String alarmId, + required UpdateAlarmRequestModel request, + }); + Future deleteAlarm({required String alarmId}); +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/datasources/alarm_remote_datasource_impl.dart b/modules/legacy/modules/settings/lib/src/core/data/datasources/alarm_remote_datasource_impl.dart new file mode 100644 index 00000000..c8fc9fa1 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/datasources/alarm_remote_datasource_impl.dart @@ -0,0 +1,75 @@ +import 'package:dio/dio.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:settings/src/core/data/datasources/alarm_remote_datasource.dart'; +import 'package:settings/src/core/data/models/create_alarm_request_model.dart'; +import 'package:settings/src/core/data/models/get_alarms_response_model.dart'; +import 'package:settings/src/core/data/models/update_alarm_request_model.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +class AlarmRemoteDatasourceImpl implements AlarmRemoteDatasource { + AlarmRemoteDatasourceImpl(this._repository); + + final QuestiaRepository _repository; + + @override + Future getAlarms({ + required String deviceId, + }) async { + try { + final response = await _repository.get>( + '/devices/$deviceId/takepills-reminders', + ); + + final data = response.data; + if (data == null || data.isEmpty) { + throw Exception( + 'Empty response from /devices/$deviceId/takepills-reminders', + ); + } + + return GetAlarmsResponseModel.fromJson(data); + } on DioException catch (error) { + throw mapDioError( + error, + defaultMessage: 'Error getting alarms', + ); + } + } + + @override + Future createAlarm({ + required CreateAlarmRequestModel request, + }) async { + await safeCall( + () => _repository.post( + '/takepills-reminders', + body: request.toJson(), + ), + 'Error creating alarm', + ); + } + + @override + Future updateAlarm({ + required String alarmId, + required UpdateAlarmRequestModel request, + }) async { + await safeCall( + () => _repository.put( + '/takepills-reminders/$alarmId', + body: request.toJson(), + ), + 'Error updating alarm', + ); + } + + @override + Future deleteAlarm({required String alarmId}) async { + await safeCall( + () => _repository.delete( + '/takepills-reminders/$alarmId', + ), + 'Error deleting alarm', + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/datasources/contact_lists_remote_datasource.dart b/modules/legacy/modules/settings/lib/src/core/data/datasources/contact_lists_remote_datasource.dart new file mode 100644 index 00000000..c91d6f46 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/datasources/contact_lists_remote_datasource.dart @@ -0,0 +1,12 @@ +import 'package:settings/src/core/data/models/get_contact_lists_response_model.dart'; +import 'package:settings/src/core/data/models/upsert_contact_list_request_model.dart'; + +abstract class ContactListsRemoteDatasource { + Future getContactLists({ + required String deviceId, + }); + + Future upsertContactList({ + required UpsertContactListRequestModel request, + }); +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/datasources/contact_lists_remote_datasource_impl.dart b/modules/legacy/modules/settings/lib/src/core/data/datasources/contact_lists_remote_datasource_impl.dart new file mode 100644 index 00000000..ce55f457 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/datasources/contact_lists_remote_datasource_impl.dart @@ -0,0 +1,53 @@ +import 'package:dio/dio.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import 'package:settings/src/core/data/models/get_contact_lists_response_model.dart'; +import 'package:settings/src/core/data/models/upsert_contact_list_request_model.dart'; + +import 'contact_lists_remote_datasource.dart'; + +class ContactListsRemoteDatasourceImpl + implements ContactListsRemoteDatasource { + ContactListsRemoteDatasourceImpl(this._repository); + + final QuestiaRepository _repository; + + @override + Future getContactLists({ + required String deviceId, + }) async { + try { + final response = await _repository.get>( + '/devices/$deviceId/contact-lists', + ); + + final data = response.data; + if (data == null || data.isEmpty) { + throw Exception( + 'Empty response from /devices/$deviceId/contact-lists', + ); + } + + return GetContactListsResponseModel.fromJson(data); + } on DioException catch (error) { + throw mapDioError( + error, + defaultMessage: 'Error getting contact lists', + ); + } + } + + @override + Future upsertContactList({ + required UpsertContactListRequestModel request, + }) async { + await safeCall( + () => _repository.post( + '/contact-lists', + body: request.toJson(), + ), + 'Error updating contact list', + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/datasources/language_remote_datasource.dart b/modules/legacy/modules/settings/lib/src/core/data/datasources/language_remote_datasource.dart new file mode 100644 index 00000000..9db6d482 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/datasources/language_remote_datasource.dart @@ -0,0 +1,6 @@ +abstract class LanguageRemoteDatasource { + Future updateDeviceLanguage({ + required Map deviceData, + required String newLanguage, + }); +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/datasources/language_remote_datasource_impl.dart b/modules/legacy/modules/settings/lib/src/core/data/datasources/language_remote_datasource_impl.dart new file mode 100644 index 00000000..8ff5f1e9 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/datasources/language_remote_datasource_impl.dart @@ -0,0 +1,68 @@ +import 'dart:convert'; + +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import 'language_remote_datasource.dart'; + +class LanguageRemoteDatasourceImpl implements LanguageRemoteDatasource { + LanguageRemoteDatasourceImpl(this._repository); + + final QuestiaRepository _repository; + + @override + Future updateDeviceLanguage({ + required Map deviceData, + required String newLanguage, + }) async { + final settings = Map.from( + deviceData['settings'] as Map? ?? {}, + ); + settings['language'] = newLanguage; + + final flags = Map.from( + deviceData['flags'] as Map? ?? {}, + ); + final tags = deviceData['tags'] as List? ?? []; + + final id = deviceData['id'] ?? ''; + final carrierName = deviceData['carrierName'] ?? ''; + final battery = deviceData['battery'] ?? ''; + final carrierBirthday = deviceData['carrierBirthday'] ?? ''; + final carrierWeight = deviceData['carrierWeight'] ?? ''; + final carrierStepLength = deviceData['carrierStepLength'] ?? ''; + final carrierGenre = deviceData['carrierGenre'] ?? ''; + final comment = deviceData['comment'] ?? ''; + final groupId = deviceData['groupId'] ?? ''; + final lastConnection = deviceData['lastConnection'] ?? ''; + final phone = deviceData['phone'] ?? ''; + final simId = deviceData['simId'] ?? ''; + + final paymentOptions = deviceData['paymentOptions']; + final paymentOptionsStr = paymentOptions != null + ? jsonEncode(paymentOptions) + : ''; + + final csvHeader = + 'id,carrierName,flags,settings,battery,carrierBirthday,' + 'carrierWeight,carrierStepLength,carrierGenre,comment,' + 'groupId,lastConnection,paymentOptions,phone,simId,tags'; + + final csvRow = + '$id,$carrierName,${jsonEncode(flags)},${jsonEncode(settings)},' + '$battery,$carrierBirthday,$carrierWeight,$carrierStepLength,' + '$carrierGenre,$comment,$groupId,$lastConnection,' + '$paymentOptionsStr,$phone,$simId,"${jsonEncode(tags)}"'; + + final csv = '$csvHeader\n$csvRow'; + final csvBase64 = base64Encode(utf8.encode(csv)); + + await safeCall( + () => _repository.put( + '/devices', + body: {'csv': csvBase64}, + ), + 'Error updating device language', + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/datasources/settings_remote_datasource.dart b/modules/legacy/modules/settings/lib/src/core/data/datasources/settings_remote_datasource.dart index f0b70396..6eed1043 100644 --- a/modules/legacy/modules/settings/lib/src/core/data/datasources/settings_remote_datasource.dart +++ b/modules/legacy/modules/settings/lib/src/core/data/datasources/settings_remote_datasource.dart @@ -1,4 +1,3 @@ abstract class SettingsRemoteDatasource { - // Future getLoggedUser({required String token}); } diff --git a/modules/legacy/modules/settings/lib/src/core/data/datasources/settings_remote_datasource_impl.dart b/modules/legacy/modules/settings/lib/src/core/data/datasources/settings_remote_datasource_impl.dart index 3a33bde1..f9823633 100644 --- a/modules/legacy/modules/settings/lib/src/core/data/datasources/settings_remote_datasource_impl.dart +++ b/modules/legacy/modules/settings/lib/src/core/data/datasources/settings_remote_datasource_impl.dart @@ -1,6 +1,3 @@ -import 'dart:convert'; - -import 'package:dio/dio.dart'; import 'package:settings/src/core/data/datasources/settings_remote_datasource.dart'; import 'package:sf_infrastructure/sf_infrastructure.dart'; @@ -8,66 +5,4 @@ class SettingsRemoteDatasourceImpl implements SettingsRemoteDatasource { SettingsRemoteDatasourceImpl(this._repository); final QuestiaRepository _repository; - - /*@override - Future getLoggedUser({required String token}) async { - try { - final response = await _repository.get>( - '/users/api/auth/me', - ); - final data = response.data!['item']; - if (data == null || data.isEmpty) { - throw Exception('Empty response from /auth/me'); - } - - final model = GetLoggedUserResponseModel.fromJson(data); - final model = GetLoggedUserResponseModel(item: - GetLoggedUserItemResponseModel( - id: '1111', - firstName: 'Juan', - email: 'juan@test.com', - phone: '111111111')); - return model.toEntity(); - } on DioException catch (error) { - throw _mapDioError( - error, - defaultMessage: error.message ?? 'Error getting logged user', - ); - } - }*/ -} - -Exception _mapDioError(DioException error, {required String defaultMessage}) { - final apiMsg = _extractApiMessage(error.response?.data); - final msg = apiMsg ?? error.message ?? defaultMessage; - return Exception(msg); -} - -String? _extractApiMessage(Object? data) { - if (data == null) return null; - - if (data is Map) { - final errorObj = data['error']; - if (errorObj is Map && errorObj['message'] is String) { - return (errorObj['message'] as String).trim(); - } - if (data['message'] is String) { - return (data['message'] as String).trim(); - } - return null; - } - - if (data is String) { - final raw = data.trim(); - if (raw.isEmpty) return null; - - try { - final decoded = jsonDecode(raw); - return _extractApiMessage(decoded); - } catch (_) { - return raw; - } - } - - return null; } diff --git a/modules/legacy/modules/settings/lib/src/core/data/datasources/wifi_remote_datasource.dart b/modules/legacy/modules/settings/lib/src/core/data/datasources/wifi_remote_datasource.dart new file mode 100644 index 00000000..1d8a5174 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/datasources/wifi_remote_datasource.dart @@ -0,0 +1,14 @@ +import 'package:settings/src/core/data/models/create_wifi_network_request_model.dart'; +import 'package:settings/src/core/data/models/get_wifi_networks_response_model.dart'; + +abstract class WifiRemoteDatasource { + Future getWifiNetworks({ + required String deviceId, + }); + + Future createWifiNetwork({ + required CreateWifiNetworkRequestModel request, + }); + + Future deleteWifiNetwork({required String networkId}); +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/datasources/wifi_remote_datasource_impl.dart b/modules/legacy/modules/settings/lib/src/core/data/datasources/wifi_remote_datasource_impl.dart new file mode 100644 index 00000000..87f2eac3 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/datasources/wifi_remote_datasource_impl.dart @@ -0,0 +1,56 @@ +import 'package:dio/dio.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import '../models/create_wifi_network_request_model.dart'; +import '../models/get_wifi_networks_response_model.dart'; +import 'wifi_remote_datasource.dart'; + +class WifiRemoteDatasourceImpl implements WifiRemoteDatasource { + WifiRemoteDatasourceImpl(this._repository); + + final QuestiaRepository _repository; + + @override + Future getWifiNetworks({ + required String deviceId, + }) async { + try { + final response = await _repository.get>( + '/devices/$deviceId/wifi-networks', + ); + + final data = response.data; + if (data == null || data.isEmpty) { + return const GetWifiNetworksResponseModel(total: 0, items: []); + } + + return GetWifiNetworksResponseModel.fromJson(data); + } on DioException catch (error) { + throw mapDioError(error, defaultMessage: 'Error getting WiFi networks'); + } + } + + @override + Future createWifiNetwork({ + required CreateWifiNetworkRequestModel request, + }) async { + await safeCall( + () => _repository.post( + '/wifi-networks', + body: request.toJson(), + ), + 'Error creating WiFi network', + ); + } + + @override + Future deleteWifiNetwork({required String networkId}) async { + await safeCall( + () => _repository.delete( + '/wifi-networks/$networkId', + ), + 'Error deleting WiFi network', + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/create_alarm_request_model.dart b/modules/legacy/modules/settings/lib/src/core/data/models/create_alarm_request_model.dart new file mode 100644 index 00000000..0b4578fe --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/create_alarm_request_model.dart @@ -0,0 +1,18 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'create_alarm_request_model.freezed.dart'; +part 'create_alarm_request_model.g.dart'; + +@freezed +abstract class CreateAlarmRequestModel with _$CreateAlarmRequestModel { + const factory CreateAlarmRequestModel({ + required String id, + required String deviceId, + required String time, + required String message, + required int order, + }) = _CreateAlarmRequestModel; + + factory CreateAlarmRequestModel.fromJson(Map json) => + _$CreateAlarmRequestModelFromJson(json); +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/create_alarm_request_model.freezed.dart b/modules/legacy/modules/settings/lib/src/core/data/models/create_alarm_request_model.freezed.dart new file mode 100644 index 00000000..2ca3399c --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/create_alarm_request_model.freezed.dart @@ -0,0 +1,289 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'create_alarm_request_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$CreateAlarmRequestModel { + + String get id; String get deviceId; String get time; String get message; int get order; +/// Create a copy of CreateAlarmRequestModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CreateAlarmRequestModelCopyWith get copyWith => _$CreateAlarmRequestModelCopyWithImpl(this as CreateAlarmRequestModel, _$identity); + + /// Serializes this CreateAlarmRequestModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CreateAlarmRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.time, time) || other.time == time)&&(identical(other.message, message) || other.message == message)&&(identical(other.order, order) || other.order == order)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,time,message,order); + +@override +String toString() { + return 'CreateAlarmRequestModel(id: $id, deviceId: $deviceId, time: $time, message: $message, order: $order)'; +} + + +} + +/// @nodoc +abstract mixin class $CreateAlarmRequestModelCopyWith<$Res> { + factory $CreateAlarmRequestModelCopyWith(CreateAlarmRequestModel value, $Res Function(CreateAlarmRequestModel) _then) = _$CreateAlarmRequestModelCopyWithImpl; +@useResult +$Res call({ + String id, String deviceId, String time, String message, int order +}); + + + + +} +/// @nodoc +class _$CreateAlarmRequestModelCopyWithImpl<$Res> + implements $CreateAlarmRequestModelCopyWith<$Res> { + _$CreateAlarmRequestModelCopyWithImpl(this._self, this._then); + + final CreateAlarmRequestModel _self; + final $Res Function(CreateAlarmRequestModel) _then; + +/// Create a copy of CreateAlarmRequestModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceId = null,Object? time = null,Object? message = null,Object? order = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,time: null == time ? _self.time : time // ignore: cast_nullable_to_non_nullable +as String,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,order: null == order ? _self.order : order // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [CreateAlarmRequestModel]. +extension CreateAlarmRequestModelPatterns on CreateAlarmRequestModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _CreateAlarmRequestModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _CreateAlarmRequestModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _CreateAlarmRequestModel value) $default,){ +final _that = this; +switch (_that) { +case _CreateAlarmRequestModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _CreateAlarmRequestModel value)? $default,){ +final _that = this; +switch (_that) { +case _CreateAlarmRequestModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceId, String time, String message, int order)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _CreateAlarmRequestModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.time,_that.message,_that.order);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceId, String time, String message, int order) $default,) {final _that = this; +switch (_that) { +case _CreateAlarmRequestModel(): +return $default(_that.id,_that.deviceId,_that.time,_that.message,_that.order);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceId, String time, String message, int order)? $default,) {final _that = this; +switch (_that) { +case _CreateAlarmRequestModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.time,_that.message,_that.order);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _CreateAlarmRequestModel implements CreateAlarmRequestModel { + const _CreateAlarmRequestModel({required this.id, required this.deviceId, required this.time, required this.message, required this.order}); + factory _CreateAlarmRequestModel.fromJson(Map json) => _$CreateAlarmRequestModelFromJson(json); + +@override final String id; +@override final String deviceId; +@override final String time; +@override final String message; +@override final int order; + +/// Create a copy of CreateAlarmRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$CreateAlarmRequestModelCopyWith<_CreateAlarmRequestModel> get copyWith => __$CreateAlarmRequestModelCopyWithImpl<_CreateAlarmRequestModel>(this, _$identity); + +@override +Map toJson() { + return _$CreateAlarmRequestModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _CreateAlarmRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.time, time) || other.time == time)&&(identical(other.message, message) || other.message == message)&&(identical(other.order, order) || other.order == order)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,time,message,order); + +@override +String toString() { + return 'CreateAlarmRequestModel(id: $id, deviceId: $deviceId, time: $time, message: $message, order: $order)'; +} + + +} + +/// @nodoc +abstract mixin class _$CreateAlarmRequestModelCopyWith<$Res> implements $CreateAlarmRequestModelCopyWith<$Res> { + factory _$CreateAlarmRequestModelCopyWith(_CreateAlarmRequestModel value, $Res Function(_CreateAlarmRequestModel) _then) = __$CreateAlarmRequestModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceId, String time, String message, int order +}); + + + + +} +/// @nodoc +class __$CreateAlarmRequestModelCopyWithImpl<$Res> + implements _$CreateAlarmRequestModelCopyWith<$Res> { + __$CreateAlarmRequestModelCopyWithImpl(this._self, this._then); + + final _CreateAlarmRequestModel _self; + final $Res Function(_CreateAlarmRequestModel) _then; + +/// Create a copy of CreateAlarmRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceId = null,Object? time = null,Object? message = null,Object? order = null,}) { + return _then(_CreateAlarmRequestModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,time: null == time ? _self.time : time // ignore: cast_nullable_to_non_nullable +as String,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,order: null == order ? _self.order : order // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/create_alarm_request_model.g.dart b/modules/legacy/modules/settings/lib/src/core/data/models/create_alarm_request_model.g.dart new file mode 100644 index 00000000..96e87733 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/create_alarm_request_model.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'create_alarm_request_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_CreateAlarmRequestModel _$CreateAlarmRequestModelFromJson( + Map json, +) => _CreateAlarmRequestModel( + id: json['id'] as String, + deviceId: json['deviceId'] as String, + time: json['time'] as String, + message: json['message'] as String, + order: (json['order'] as num).toInt(), +); + +Map _$CreateAlarmRequestModelToJson( + _CreateAlarmRequestModel instance, +) => { + 'id': instance.id, + 'deviceId': instance.deviceId, + 'time': instance.time, + 'message': instance.message, + 'order': instance.order, +}; diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/create_wifi_network_request_model.dart b/modules/legacy/modules/settings/lib/src/core/data/models/create_wifi_network_request_model.dart new file mode 100644 index 00000000..d85fc8b4 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/create_wifi_network_request_model.dart @@ -0,0 +1,18 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'create_wifi_network_request_model.freezed.dart'; +part 'create_wifi_network_request_model.g.dart'; + +@freezed +abstract class CreateWifiNetworkRequestModel + with _$CreateWifiNetworkRequestModel { + const factory CreateWifiNetworkRequestModel({ + required String id, + required String deviceId, + required String ssid, + required String bssid, + }) = _CreateWifiNetworkRequestModel; + + factory CreateWifiNetworkRequestModel.fromJson(Map json) => + _$CreateWifiNetworkRequestModelFromJson(json); +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/create_wifi_network_request_model.freezed.dart b/modules/legacy/modules/settings/lib/src/core/data/models/create_wifi_network_request_model.freezed.dart new file mode 100644 index 00000000..f29912fe --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/create_wifi_network_request_model.freezed.dart @@ -0,0 +1,286 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'create_wifi_network_request_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$CreateWifiNetworkRequestModel { + + String get id; String get deviceId; String get ssid; String get bssid; +/// Create a copy of CreateWifiNetworkRequestModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CreateWifiNetworkRequestModelCopyWith get copyWith => _$CreateWifiNetworkRequestModelCopyWithImpl(this as CreateWifiNetworkRequestModel, _$identity); + + /// Serializes this CreateWifiNetworkRequestModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CreateWifiNetworkRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.ssid, ssid) || other.ssid == ssid)&&(identical(other.bssid, bssid) || other.bssid == bssid)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,ssid,bssid); + +@override +String toString() { + return 'CreateWifiNetworkRequestModel(id: $id, deviceId: $deviceId, ssid: $ssid, bssid: $bssid)'; +} + + +} + +/// @nodoc +abstract mixin class $CreateWifiNetworkRequestModelCopyWith<$Res> { + factory $CreateWifiNetworkRequestModelCopyWith(CreateWifiNetworkRequestModel value, $Res Function(CreateWifiNetworkRequestModel) _then) = _$CreateWifiNetworkRequestModelCopyWithImpl; +@useResult +$Res call({ + String id, String deviceId, String ssid, String bssid +}); + + + + +} +/// @nodoc +class _$CreateWifiNetworkRequestModelCopyWithImpl<$Res> + implements $CreateWifiNetworkRequestModelCopyWith<$Res> { + _$CreateWifiNetworkRequestModelCopyWithImpl(this._self, this._then); + + final CreateWifiNetworkRequestModel _self; + final $Res Function(CreateWifiNetworkRequestModel) _then; + +/// Create a copy of CreateWifiNetworkRequestModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceId = null,Object? ssid = null,Object? bssid = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,ssid: null == ssid ? _self.ssid : ssid // ignore: cast_nullable_to_non_nullable +as String,bssid: null == bssid ? _self.bssid : bssid // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [CreateWifiNetworkRequestModel]. +extension CreateWifiNetworkRequestModelPatterns on CreateWifiNetworkRequestModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _CreateWifiNetworkRequestModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _CreateWifiNetworkRequestModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _CreateWifiNetworkRequestModel value) $default,){ +final _that = this; +switch (_that) { +case _CreateWifiNetworkRequestModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _CreateWifiNetworkRequestModel value)? $default,){ +final _that = this; +switch (_that) { +case _CreateWifiNetworkRequestModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceId, String ssid, String bssid)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _CreateWifiNetworkRequestModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.ssid,_that.bssid);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceId, String ssid, String bssid) $default,) {final _that = this; +switch (_that) { +case _CreateWifiNetworkRequestModel(): +return $default(_that.id,_that.deviceId,_that.ssid,_that.bssid);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceId, String ssid, String bssid)? $default,) {final _that = this; +switch (_that) { +case _CreateWifiNetworkRequestModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.ssid,_that.bssid);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _CreateWifiNetworkRequestModel implements CreateWifiNetworkRequestModel { + const _CreateWifiNetworkRequestModel({required this.id, required this.deviceId, required this.ssid, required this.bssid}); + factory _CreateWifiNetworkRequestModel.fromJson(Map json) => _$CreateWifiNetworkRequestModelFromJson(json); + +@override final String id; +@override final String deviceId; +@override final String ssid; +@override final String bssid; + +/// Create a copy of CreateWifiNetworkRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$CreateWifiNetworkRequestModelCopyWith<_CreateWifiNetworkRequestModel> get copyWith => __$CreateWifiNetworkRequestModelCopyWithImpl<_CreateWifiNetworkRequestModel>(this, _$identity); + +@override +Map toJson() { + return _$CreateWifiNetworkRequestModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _CreateWifiNetworkRequestModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.ssid, ssid) || other.ssid == ssid)&&(identical(other.bssid, bssid) || other.bssid == bssid)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,ssid,bssid); + +@override +String toString() { + return 'CreateWifiNetworkRequestModel(id: $id, deviceId: $deviceId, ssid: $ssid, bssid: $bssid)'; +} + + +} + +/// @nodoc +abstract mixin class _$CreateWifiNetworkRequestModelCopyWith<$Res> implements $CreateWifiNetworkRequestModelCopyWith<$Res> { + factory _$CreateWifiNetworkRequestModelCopyWith(_CreateWifiNetworkRequestModel value, $Res Function(_CreateWifiNetworkRequestModel) _then) = __$CreateWifiNetworkRequestModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceId, String ssid, String bssid +}); + + + + +} +/// @nodoc +class __$CreateWifiNetworkRequestModelCopyWithImpl<$Res> + implements _$CreateWifiNetworkRequestModelCopyWith<$Res> { + __$CreateWifiNetworkRequestModelCopyWithImpl(this._self, this._then); + + final _CreateWifiNetworkRequestModel _self; + final $Res Function(_CreateWifiNetworkRequestModel) _then; + +/// Create a copy of CreateWifiNetworkRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceId = null,Object? ssid = null,Object? bssid = null,}) { + return _then(_CreateWifiNetworkRequestModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,ssid: null == ssid ? _self.ssid : ssid // ignore: cast_nullable_to_non_nullable +as String,bssid: null == bssid ? _self.bssid : bssid // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/create_wifi_network_request_model.g.dart b/modules/legacy/modules/settings/lib/src/core/data/models/create_wifi_network_request_model.g.dart new file mode 100644 index 00000000..59cb7ce7 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/create_wifi_network_request_model.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'create_wifi_network_request_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_CreateWifiNetworkRequestModel _$CreateWifiNetworkRequestModelFromJson( + Map json, +) => _CreateWifiNetworkRequestModel( + id: json['id'] as String, + deviceId: json['deviceId'] as String, + ssid: json['ssid'] as String, + bssid: json['bssid'] as String, +); + +Map _$CreateWifiNetworkRequestModelToJson( + _CreateWifiNetworkRequestModel instance, +) => { + 'id': instance.id, + 'deviceId': instance.deviceId, + 'ssid': instance.ssid, + 'bssid': instance.bssid, +}; diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/get_alarms_response_model.dart b/modules/legacy/modules/settings/lib/src/core/data/models/get_alarms_response_model.dart new file mode 100644 index 00000000..eb007a04 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/get_alarms_response_model.dart @@ -0,0 +1,53 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:settings/src/features/alarm/domain/entities/alarm_entity.dart'; + +part 'get_alarms_response_model.freezed.dart'; +part 'get_alarms_response_model.g.dart'; + +@freezed +abstract class GetAlarmsResponseModel with _$GetAlarmsResponseModel { + const factory GetAlarmsResponseModel({ + required int total, + required List items, + required int page, + required int pages, + }) = _GetAlarmsResponseModel; + + factory GetAlarmsResponseModel.fromJson(Map json) => + _$GetAlarmsResponseModelFromJson(json); +} + +@freezed +abstract class AlarmItemResponseModel with _$AlarmItemResponseModel { + const factory AlarmItemResponseModel({ + required String id, + required String deviceId, + required String time, + required String message, + required int order, + required int createdAt, + int? updatedAt, + }) = _AlarmItemResponseModel; + + factory AlarmItemResponseModel.fromJson(Map json) => + _$AlarmItemResponseModelFromJson(json); +} + +extension AlarmsResponseMapper on GetAlarmsResponseModel { + List toEntity() { + return items.map((item) { + final decoded = AlarmEntity.decodeTime(item.time); + return AlarmEntity( + id: item.id, + deviceId: item.deviceId, + time: decoded.time, + message: item.message, + order: item.order, + dateOption: decoded.dateOption, + days: decoded.days, + createdAt: item.createdAt, + updatedAt: item.updatedAt, + ); + }).toList(); + } +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/get_alarms_response_model.freezed.dart b/modules/legacy/modules/settings/lib/src/core/data/models/get_alarms_response_model.freezed.dart new file mode 100644 index 00000000..79fd7204 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/get_alarms_response_model.freezed.dart @@ -0,0 +1,573 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'get_alarms_response_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$GetAlarmsResponseModel { + + int get total; List get items; int get page; int get pages; +/// Create a copy of GetAlarmsResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$GetAlarmsResponseModelCopyWith get copyWith => _$GetAlarmsResponseModelCopyWithImpl(this as GetAlarmsResponseModel, _$identity); + + /// Serializes this GetAlarmsResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is GetAlarmsResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other.items, items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(items),page,pages); + +@override +String toString() { + return 'GetAlarmsResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class $GetAlarmsResponseModelCopyWith<$Res> { + factory $GetAlarmsResponseModelCopyWith(GetAlarmsResponseModel value, $Res Function(GetAlarmsResponseModel) _then) = _$GetAlarmsResponseModelCopyWithImpl; +@useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class _$GetAlarmsResponseModelCopyWithImpl<$Res> + implements $GetAlarmsResponseModelCopyWith<$Res> { + _$GetAlarmsResponseModelCopyWithImpl(this._self, this._then); + + final GetAlarmsResponseModel _self; + final $Res Function(GetAlarmsResponseModel) _then; + +/// Create a copy of GetAlarmsResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_self.copyWith( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [GetAlarmsResponseModel]. +extension GetAlarmsResponseModelPatterns on GetAlarmsResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _GetAlarmsResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _GetAlarmsResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _GetAlarmsResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _GetAlarmsResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _GetAlarmsResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _GetAlarmsResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int total, List items, int page, int pages)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _GetAlarmsResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int total, List items, int page, int pages) $default,) {final _that = this; +switch (_that) { +case _GetAlarmsResponseModel(): +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int total, List items, int page, int pages)? $default,) {final _that = this; +switch (_that) { +case _GetAlarmsResponseModel() when $default != null: +return $default(_that.total,_that.items,_that.page,_that.pages);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _GetAlarmsResponseModel implements GetAlarmsResponseModel { + const _GetAlarmsResponseModel({required this.total, required final List items, required this.page, required this.pages}): _items = items; + factory _GetAlarmsResponseModel.fromJson(Map json) => _$GetAlarmsResponseModelFromJson(json); + +@override final int total; + final List _items; +@override List get items { + if (_items is EqualUnmodifiableListView) return _items; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_items); +} + +@override final int page; +@override final int pages; + +/// Create a copy of GetAlarmsResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$GetAlarmsResponseModelCopyWith<_GetAlarmsResponseModel> get copyWith => __$GetAlarmsResponseModelCopyWithImpl<_GetAlarmsResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$GetAlarmsResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetAlarmsResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other._items, _items)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(_items),page,pages); + +@override +String toString() { + return 'GetAlarmsResponseModel(total: $total, items: $items, page: $page, pages: $pages)'; +} + + +} + +/// @nodoc +abstract mixin class _$GetAlarmsResponseModelCopyWith<$Res> implements $GetAlarmsResponseModelCopyWith<$Res> { + factory _$GetAlarmsResponseModelCopyWith(_GetAlarmsResponseModel value, $Res Function(_GetAlarmsResponseModel) _then) = __$GetAlarmsResponseModelCopyWithImpl; +@override @useResult +$Res call({ + int total, List items, int page, int pages +}); + + + + +} +/// @nodoc +class __$GetAlarmsResponseModelCopyWithImpl<$Res> + implements _$GetAlarmsResponseModelCopyWith<$Res> { + __$GetAlarmsResponseModelCopyWithImpl(this._self, this._then); + + final _GetAlarmsResponseModel _self; + final $Res Function(_GetAlarmsResponseModel) _then; + +/// Create a copy of GetAlarmsResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? total = null,Object? items = null,Object? page = null,Object? pages = null,}) { + return _then(_GetAlarmsResponseModel( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable +as List,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable +as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + + +/// @nodoc +mixin _$AlarmItemResponseModel { + + String get id; String get deviceId; String get time; String get message; int get order; int get createdAt; int? get updatedAt; +/// Create a copy of AlarmItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AlarmItemResponseModelCopyWith get copyWith => _$AlarmItemResponseModelCopyWithImpl(this as AlarmItemResponseModel, _$identity); + + /// Serializes this AlarmItemResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AlarmItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.time, time) || other.time == time)&&(identical(other.message, message) || other.message == message)&&(identical(other.order, order) || other.order == order)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,time,message,order,createdAt,updatedAt); + +@override +String toString() { + return 'AlarmItemResponseModel(id: $id, deviceId: $deviceId, time: $time, message: $message, order: $order, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class $AlarmItemResponseModelCopyWith<$Res> { + factory $AlarmItemResponseModelCopyWith(AlarmItemResponseModel value, $Res Function(AlarmItemResponseModel) _then) = _$AlarmItemResponseModelCopyWithImpl; +@useResult +$Res call({ + String id, String deviceId, String time, String message, int order, int createdAt, int? updatedAt +}); + + + + +} +/// @nodoc +class _$AlarmItemResponseModelCopyWithImpl<$Res> + implements $AlarmItemResponseModelCopyWith<$Res> { + _$AlarmItemResponseModelCopyWithImpl(this._self, this._then); + + final AlarmItemResponseModel _self; + final $Res Function(AlarmItemResponseModel) _then; + +/// Create a copy of AlarmItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceId = null,Object? time = null,Object? message = null,Object? order = null,Object? createdAt = null,Object? updatedAt = freezed,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,time: null == time ? _self.time : time // ignore: cast_nullable_to_non_nullable +as String,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,order: null == order ? _self.order : order // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [AlarmItemResponseModel]. +extension AlarmItemResponseModelPatterns on AlarmItemResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AlarmItemResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AlarmItemResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AlarmItemResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _AlarmItemResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AlarmItemResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _AlarmItemResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceId, String time, String message, int order, int createdAt, int? updatedAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AlarmItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.time,_that.message,_that.order,_that.createdAt,_that.updatedAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceId, String time, String message, int order, int createdAt, int? updatedAt) $default,) {final _that = this; +switch (_that) { +case _AlarmItemResponseModel(): +return $default(_that.id,_that.deviceId,_that.time,_that.message,_that.order,_that.createdAt,_that.updatedAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceId, String time, String message, int order, int createdAt, int? updatedAt)? $default,) {final _that = this; +switch (_that) { +case _AlarmItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.time,_that.message,_that.order,_that.createdAt,_that.updatedAt);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _AlarmItemResponseModel implements AlarmItemResponseModel { + const _AlarmItemResponseModel({required this.id, required this.deviceId, required this.time, required this.message, required this.order, required this.createdAt, this.updatedAt}); + factory _AlarmItemResponseModel.fromJson(Map json) => _$AlarmItemResponseModelFromJson(json); + +@override final String id; +@override final String deviceId; +@override final String time; +@override final String message; +@override final int order; +@override final int createdAt; +@override final int? updatedAt; + +/// Create a copy of AlarmItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AlarmItemResponseModelCopyWith<_AlarmItemResponseModel> get copyWith => __$AlarmItemResponseModelCopyWithImpl<_AlarmItemResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$AlarmItemResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AlarmItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.time, time) || other.time == time)&&(identical(other.message, message) || other.message == message)&&(identical(other.order, order) || other.order == order)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,time,message,order,createdAt,updatedAt); + +@override +String toString() { + return 'AlarmItemResponseModel(id: $id, deviceId: $deviceId, time: $time, message: $message, order: $order, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$AlarmItemResponseModelCopyWith<$Res> implements $AlarmItemResponseModelCopyWith<$Res> { + factory _$AlarmItemResponseModelCopyWith(_AlarmItemResponseModel value, $Res Function(_AlarmItemResponseModel) _then) = __$AlarmItemResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceId, String time, String message, int order, int createdAt, int? updatedAt +}); + + + + +} +/// @nodoc +class __$AlarmItemResponseModelCopyWithImpl<$Res> + implements _$AlarmItemResponseModelCopyWith<$Res> { + __$AlarmItemResponseModelCopyWithImpl(this._self, this._then); + + final _AlarmItemResponseModel _self; + final $Res Function(_AlarmItemResponseModel) _then; + +/// Create a copy of AlarmItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceId = null,Object? time = null,Object? message = null,Object? order = null,Object? createdAt = null,Object? updatedAt = freezed,}) { + return _then(_AlarmItemResponseModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,time: null == time ? _self.time : time // ignore: cast_nullable_to_non_nullable +as String,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,order: null == order ? _self.order : order // ignore: cast_nullable_to_non_nullable +as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/get_alarms_response_model.g.dart b/modules/legacy/modules/settings/lib/src/core/data/models/get_alarms_response_model.g.dart new file mode 100644 index 00000000..55002be1 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/get_alarms_response_model.g.dart @@ -0,0 +1,51 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_alarms_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_GetAlarmsResponseModel _$GetAlarmsResponseModelFromJson( + Map json, +) => _GetAlarmsResponseModel( + total: (json['total'] as num).toInt(), + items: (json['items'] as List) + .map((e) => AlarmItemResponseModel.fromJson(e as Map)) + .toList(), + page: (json['page'] as num).toInt(), + pages: (json['pages'] as num).toInt(), +); + +Map _$GetAlarmsResponseModelToJson( + _GetAlarmsResponseModel instance, +) => { + 'total': instance.total, + 'items': instance.items, + 'page': instance.page, + 'pages': instance.pages, +}; + +_AlarmItemResponseModel _$AlarmItemResponseModelFromJson( + Map json, +) => _AlarmItemResponseModel( + id: json['id'] as String, + deviceId: json['deviceId'] as String, + time: json['time'] as String, + message: json['message'] as String, + order: (json['order'] as num).toInt(), + createdAt: (json['createdAt'] as num).toInt(), + updatedAt: (json['updatedAt'] as num?)?.toInt(), +); + +Map _$AlarmItemResponseModelToJson( + _AlarmItemResponseModel instance, +) => { + 'id': instance.id, + 'deviceId': instance.deviceId, + 'time': instance.time, + 'message': instance.message, + 'order': instance.order, + 'createdAt': instance.createdAt, + 'updatedAt': instance.updatedAt, +}; diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/get_contact_lists_response_model.dart b/modules/legacy/modules/settings/lib/src/core/data/models/get_contact_lists_response_model.dart new file mode 100644 index 00000000..97198e4d --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/get_contact_lists_response_model.dart @@ -0,0 +1,46 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'get_contact_lists_response_model.freezed.dart'; +part 'get_contact_lists_response_model.g.dart'; + +@freezed +abstract class GetContactListsResponseModel + with _$GetContactListsResponseModel { + const factory GetContactListsResponseModel({ + required List items, + }) = _GetContactListsResponseModel; + + factory GetContactListsResponseModel.fromJson(Map json) => + _$GetContactListsResponseModelFromJson(json); +} + +@freezed +abstract class ContactListItemResponseModel + with _$ContactListItemResponseModel { + const factory ContactListItemResponseModel({ + required String id, + required String userId, + required String deviceId, + required String type, + required List contacts, + required int createdAt, + int? updatedAt, + }) = _ContactListItemResponseModel; + + factory ContactListItemResponseModel.fromJson(Map json) => + _$ContactListItemResponseModelFromJson(json); +} + +@freezed +abstract class ContactListContactResponseModel + with _$ContactListContactResponseModel { + const factory ContactListContactResponseModel({ + required String name, + required String phone, + }) = _ContactListContactResponseModel; + + factory ContactListContactResponseModel.fromJson( + Map json, + ) => + _$ContactListContactResponseModelFromJson(json); +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/get_contact_lists_response_model.freezed.dart b/modules/legacy/modules/settings/lib/src/core/data/models/get_contact_lists_response_model.freezed.dart new file mode 100644 index 00000000..a38d9241 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/get_contact_lists_response_model.freezed.dart @@ -0,0 +1,836 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'get_contact_lists_response_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$GetContactListsResponseModel { + + List get items; +/// Create a copy of GetContactListsResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$GetContactListsResponseModelCopyWith get copyWith => _$GetContactListsResponseModelCopyWithImpl(this as GetContactListsResponseModel, _$identity); + + /// Serializes this GetContactListsResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is GetContactListsResponseModel&&const DeepCollectionEquality().equals(other.items, items)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(items)); + +@override +String toString() { + return 'GetContactListsResponseModel(items: $items)'; +} + + +} + +/// @nodoc +abstract mixin class $GetContactListsResponseModelCopyWith<$Res> { + factory $GetContactListsResponseModelCopyWith(GetContactListsResponseModel value, $Res Function(GetContactListsResponseModel) _then) = _$GetContactListsResponseModelCopyWithImpl; +@useResult +$Res call({ + List items +}); + + + + +} +/// @nodoc +class _$GetContactListsResponseModelCopyWithImpl<$Res> + implements $GetContactListsResponseModelCopyWith<$Res> { + _$GetContactListsResponseModelCopyWithImpl(this._self, this._then); + + final GetContactListsResponseModel _self; + final $Res Function(GetContactListsResponseModel) _then; + +/// Create a copy of GetContactListsResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? items = null,}) { + return _then(_self.copyWith( +items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable +as List, + )); +} + +} + + +/// Adds pattern-matching-related methods to [GetContactListsResponseModel]. +extension GetContactListsResponseModelPatterns on GetContactListsResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _GetContactListsResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _GetContactListsResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _GetContactListsResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _GetContactListsResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _GetContactListsResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _GetContactListsResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( List items)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _GetContactListsResponseModel() when $default != null: +return $default(_that.items);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( List items) $default,) {final _that = this; +switch (_that) { +case _GetContactListsResponseModel(): +return $default(_that.items);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List items)? $default,) {final _that = this; +switch (_that) { +case _GetContactListsResponseModel() when $default != null: +return $default(_that.items);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _GetContactListsResponseModel implements GetContactListsResponseModel { + const _GetContactListsResponseModel({required final List items}): _items = items; + factory _GetContactListsResponseModel.fromJson(Map json) => _$GetContactListsResponseModelFromJson(json); + + final List _items; +@override List get items { + if (_items is EqualUnmodifiableListView) return _items; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_items); +} + + +/// Create a copy of GetContactListsResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$GetContactListsResponseModelCopyWith<_GetContactListsResponseModel> get copyWith => __$GetContactListsResponseModelCopyWithImpl<_GetContactListsResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$GetContactListsResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetContactListsResponseModel&&const DeepCollectionEquality().equals(other._items, _items)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_items)); + +@override +String toString() { + return 'GetContactListsResponseModel(items: $items)'; +} + + +} + +/// @nodoc +abstract mixin class _$GetContactListsResponseModelCopyWith<$Res> implements $GetContactListsResponseModelCopyWith<$Res> { + factory _$GetContactListsResponseModelCopyWith(_GetContactListsResponseModel value, $Res Function(_GetContactListsResponseModel) _then) = __$GetContactListsResponseModelCopyWithImpl; +@override @useResult +$Res call({ + List items +}); + + + + +} +/// @nodoc +class __$GetContactListsResponseModelCopyWithImpl<$Res> + implements _$GetContactListsResponseModelCopyWith<$Res> { + __$GetContactListsResponseModelCopyWithImpl(this._self, this._then); + + final _GetContactListsResponseModel _self; + final $Res Function(_GetContactListsResponseModel) _then; + +/// Create a copy of GetContactListsResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? items = null,}) { + return _then(_GetContactListsResponseModel( +items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable +as List, + )); +} + + +} + + +/// @nodoc +mixin _$ContactListItemResponseModel { + + String get id; String get userId; String get deviceId; String get type; List get contacts; int get createdAt; int? get updatedAt; +/// Create a copy of ContactListItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ContactListItemResponseModelCopyWith get copyWith => _$ContactListItemResponseModelCopyWithImpl(this as ContactListItemResponseModel, _$identity); + + /// Serializes this ContactListItemResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ContactListItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.contacts, contacts)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,userId,deviceId,type,const DeepCollectionEquality().hash(contacts),createdAt,updatedAt); + +@override +String toString() { + return 'ContactListItemResponseModel(id: $id, userId: $userId, deviceId: $deviceId, type: $type, contacts: $contacts, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class $ContactListItemResponseModelCopyWith<$Res> { + factory $ContactListItemResponseModelCopyWith(ContactListItemResponseModel value, $Res Function(ContactListItemResponseModel) _then) = _$ContactListItemResponseModelCopyWithImpl; +@useResult +$Res call({ + String id, String userId, String deviceId, String type, List contacts, int createdAt, int? updatedAt +}); + + + + +} +/// @nodoc +class _$ContactListItemResponseModelCopyWithImpl<$Res> + implements $ContactListItemResponseModelCopyWith<$Res> { + _$ContactListItemResponseModelCopyWithImpl(this._self, this._then); + + final ContactListItemResponseModel _self; + final $Res Function(ContactListItemResponseModel) _then; + +/// Create a copy of ContactListItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? userId = null,Object? deviceId = null,Object? type = null,Object? contacts = null,Object? createdAt = null,Object? updatedAt = freezed,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable +as String,contacts: null == contacts ? _self.contacts : contacts // ignore: cast_nullable_to_non_nullable +as List,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [ContactListItemResponseModel]. +extension ContactListItemResponseModelPatterns on ContactListItemResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _ContactListItemResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _ContactListItemResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _ContactListItemResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _ContactListItemResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ContactListItemResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _ContactListItemResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String userId, String deviceId, String type, List contacts, int createdAt, int? updatedAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _ContactListItemResponseModel() when $default != null: +return $default(_that.id,_that.userId,_that.deviceId,_that.type,_that.contacts,_that.createdAt,_that.updatedAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String userId, String deviceId, String type, List contacts, int createdAt, int? updatedAt) $default,) {final _that = this; +switch (_that) { +case _ContactListItemResponseModel(): +return $default(_that.id,_that.userId,_that.deviceId,_that.type,_that.contacts,_that.createdAt,_that.updatedAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String userId, String deviceId, String type, List contacts, int createdAt, int? updatedAt)? $default,) {final _that = this; +switch (_that) { +case _ContactListItemResponseModel() when $default != null: +return $default(_that.id,_that.userId,_that.deviceId,_that.type,_that.contacts,_that.createdAt,_that.updatedAt);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _ContactListItemResponseModel implements ContactListItemResponseModel { + const _ContactListItemResponseModel({required this.id, required this.userId, required this.deviceId, required this.type, required final List contacts, required this.createdAt, this.updatedAt}): _contacts = contacts; + factory _ContactListItemResponseModel.fromJson(Map json) => _$ContactListItemResponseModelFromJson(json); + +@override final String id; +@override final String userId; +@override final String deviceId; +@override final String type; + final List _contacts; +@override List get contacts { + if (_contacts is EqualUnmodifiableListView) return _contacts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_contacts); +} + +@override final int createdAt; +@override final int? updatedAt; + +/// Create a copy of ContactListItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ContactListItemResponseModelCopyWith<_ContactListItemResponseModel> get copyWith => __$ContactListItemResponseModelCopyWithImpl<_ContactListItemResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$ContactListItemResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ContactListItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._contacts, _contacts)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,userId,deviceId,type,const DeepCollectionEquality().hash(_contacts),createdAt,updatedAt); + +@override +String toString() { + return 'ContactListItemResponseModel(id: $id, userId: $userId, deviceId: $deviceId, type: $type, contacts: $contacts, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$ContactListItemResponseModelCopyWith<$Res> implements $ContactListItemResponseModelCopyWith<$Res> { + factory _$ContactListItemResponseModelCopyWith(_ContactListItemResponseModel value, $Res Function(_ContactListItemResponseModel) _then) = __$ContactListItemResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String userId, String deviceId, String type, List contacts, int createdAt, int? updatedAt +}); + + + + +} +/// @nodoc +class __$ContactListItemResponseModelCopyWithImpl<$Res> + implements _$ContactListItemResponseModelCopyWith<$Res> { + __$ContactListItemResponseModelCopyWithImpl(this._self, this._then); + + final _ContactListItemResponseModel _self; + final $Res Function(_ContactListItemResponseModel) _then; + +/// Create a copy of ContactListItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? userId = null,Object? deviceId = null,Object? type = null,Object? contacts = null,Object? createdAt = null,Object? updatedAt = freezed,}) { + return _then(_ContactListItemResponseModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable +as String,contacts: null == contacts ? _self._contacts : contacts // ignore: cast_nullable_to_non_nullable +as List,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + + +} + + +/// @nodoc +mixin _$ContactListContactResponseModel { + + String get name; String get phone; +/// Create a copy of ContactListContactResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ContactListContactResponseModelCopyWith get copyWith => _$ContactListContactResponseModelCopyWithImpl(this as ContactListContactResponseModel, _$identity); + + /// Serializes this ContactListContactResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ContactListContactResponseModel&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,name,phone); + +@override +String toString() { + return 'ContactListContactResponseModel(name: $name, phone: $phone)'; +} + + +} + +/// @nodoc +abstract mixin class $ContactListContactResponseModelCopyWith<$Res> { + factory $ContactListContactResponseModelCopyWith(ContactListContactResponseModel value, $Res Function(ContactListContactResponseModel) _then) = _$ContactListContactResponseModelCopyWithImpl; +@useResult +$Res call({ + String name, String phone +}); + + + + +} +/// @nodoc +class _$ContactListContactResponseModelCopyWithImpl<$Res> + implements $ContactListContactResponseModelCopyWith<$Res> { + _$ContactListContactResponseModelCopyWithImpl(this._self, this._then); + + final ContactListContactResponseModel _self; + final $Res Function(ContactListContactResponseModel) _then; + +/// Create a copy of ContactListContactResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? name = null,Object? phone = null,}) { + return _then(_self.copyWith( +name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [ContactListContactResponseModel]. +extension ContactListContactResponseModelPatterns on ContactListContactResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _ContactListContactResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _ContactListContactResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _ContactListContactResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _ContactListContactResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ContactListContactResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _ContactListContactResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String name, String phone)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _ContactListContactResponseModel() when $default != null: +return $default(_that.name,_that.phone);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String name, String phone) $default,) {final _that = this; +switch (_that) { +case _ContactListContactResponseModel(): +return $default(_that.name,_that.phone);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String name, String phone)? $default,) {final _that = this; +switch (_that) { +case _ContactListContactResponseModel() when $default != null: +return $default(_that.name,_that.phone);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _ContactListContactResponseModel implements ContactListContactResponseModel { + const _ContactListContactResponseModel({required this.name, required this.phone}); + factory _ContactListContactResponseModel.fromJson(Map json) => _$ContactListContactResponseModelFromJson(json); + +@override final String name; +@override final String phone; + +/// Create a copy of ContactListContactResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ContactListContactResponseModelCopyWith<_ContactListContactResponseModel> get copyWith => __$ContactListContactResponseModelCopyWithImpl<_ContactListContactResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$ContactListContactResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ContactListContactResponseModel&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,name,phone); + +@override +String toString() { + return 'ContactListContactResponseModel(name: $name, phone: $phone)'; +} + + +} + +/// @nodoc +abstract mixin class _$ContactListContactResponseModelCopyWith<$Res> implements $ContactListContactResponseModelCopyWith<$Res> { + factory _$ContactListContactResponseModelCopyWith(_ContactListContactResponseModel value, $Res Function(_ContactListContactResponseModel) _then) = __$ContactListContactResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String name, String phone +}); + + + + +} +/// @nodoc +class __$ContactListContactResponseModelCopyWithImpl<$Res> + implements _$ContactListContactResponseModelCopyWith<$Res> { + __$ContactListContactResponseModelCopyWithImpl(this._self, this._then); + + final _ContactListContactResponseModel _self; + final $Res Function(_ContactListContactResponseModel) _then; + +/// Create a copy of ContactListContactResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? name = null,Object? phone = null,}) { + return _then(_ContactListContactResponseModel( +name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/get_contact_lists_response_model.g.dart b/modules/legacy/modules/settings/lib/src/core/data/models/get_contact_lists_response_model.g.dart new file mode 100644 index 00000000..0589e7b4 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/get_contact_lists_response_model.g.dart @@ -0,0 +1,61 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_contact_lists_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_GetContactListsResponseModel _$GetContactListsResponseModelFromJson( + Map json, +) => _GetContactListsResponseModel( + items: (json['items'] as List) + .map( + (e) => ContactListItemResponseModel.fromJson(e as Map), + ) + .toList(), +); + +Map _$GetContactListsResponseModelToJson( + _GetContactListsResponseModel instance, +) => {'items': instance.items}; + +_ContactListItemResponseModel _$ContactListItemResponseModelFromJson( + Map json, +) => _ContactListItemResponseModel( + id: json['id'] as String, + userId: json['userId'] as String, + deviceId: json['deviceId'] as String, + type: json['type'] as String, + contacts: (json['contacts'] as List) + .map( + (e) => + ContactListContactResponseModel.fromJson(e as Map), + ) + .toList(), + createdAt: (json['createdAt'] as num).toInt(), + updatedAt: (json['updatedAt'] as num?)?.toInt(), +); + +Map _$ContactListItemResponseModelToJson( + _ContactListItemResponseModel instance, +) => { + 'id': instance.id, + 'userId': instance.userId, + 'deviceId': instance.deviceId, + 'type': instance.type, + 'contacts': instance.contacts, + 'createdAt': instance.createdAt, + 'updatedAt': instance.updatedAt, +}; + +_ContactListContactResponseModel _$ContactListContactResponseModelFromJson( + Map json, +) => _ContactListContactResponseModel( + name: json['name'] as String, + phone: json['phone'] as String, +); + +Map _$ContactListContactResponseModelToJson( + _ContactListContactResponseModel instance, +) => {'name': instance.name, 'phone': instance.phone}; diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/get_wifi_networks_response_model.dart b/modules/legacy/modules/settings/lib/src/core/data/models/get_wifi_networks_response_model.dart new file mode 100644 index 00000000..d11f69a5 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/get_wifi_networks_response_model.dart @@ -0,0 +1,32 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'get_wifi_networks_response_model.freezed.dart'; +part 'get_wifi_networks_response_model.g.dart'; + +@freezed +abstract class GetWifiNetworksResponseModel + with _$GetWifiNetworksResponseModel { + const factory GetWifiNetworksResponseModel({ + required int total, + required List items, + }) = _GetWifiNetworksResponseModel; + + factory GetWifiNetworksResponseModel.fromJson(Map json) => + _$GetWifiNetworksResponseModelFromJson(json); +} + +@freezed +abstract class WifiNetworkItemResponseModel + with _$WifiNetworkItemResponseModel { + const factory WifiNetworkItemResponseModel({ + required String id, + required String deviceId, + required String ssid, + required String bssid, + required int createdAt, + int? updatedAt, + }) = _WifiNetworkItemResponseModel; + + factory WifiNetworkItemResponseModel.fromJson(Map json) => + _$WifiNetworkItemResponseModelFromJson(json); +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/get_wifi_networks_response_model.freezed.dart b/modules/legacy/modules/settings/lib/src/core/data/models/get_wifi_networks_response_model.freezed.dart new file mode 100644 index 00000000..da20470f --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/get_wifi_networks_response_model.freezed.dart @@ -0,0 +1,564 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'get_wifi_networks_response_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$GetWifiNetworksResponseModel { + + int get total; List get items; +/// Create a copy of GetWifiNetworksResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$GetWifiNetworksResponseModelCopyWith get copyWith => _$GetWifiNetworksResponseModelCopyWithImpl(this as GetWifiNetworksResponseModel, _$identity); + + /// Serializes this GetWifiNetworksResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is GetWifiNetworksResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other.items, items)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(items)); + +@override +String toString() { + return 'GetWifiNetworksResponseModel(total: $total, items: $items)'; +} + + +} + +/// @nodoc +abstract mixin class $GetWifiNetworksResponseModelCopyWith<$Res> { + factory $GetWifiNetworksResponseModelCopyWith(GetWifiNetworksResponseModel value, $Res Function(GetWifiNetworksResponseModel) _then) = _$GetWifiNetworksResponseModelCopyWithImpl; +@useResult +$Res call({ + int total, List items +}); + + + + +} +/// @nodoc +class _$GetWifiNetworksResponseModelCopyWithImpl<$Res> + implements $GetWifiNetworksResponseModelCopyWith<$Res> { + _$GetWifiNetworksResponseModelCopyWithImpl(this._self, this._then); + + final GetWifiNetworksResponseModel _self; + final $Res Function(GetWifiNetworksResponseModel) _then; + +/// Create a copy of GetWifiNetworksResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? total = null,Object? items = null,}) { + return _then(_self.copyWith( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable +as List, + )); +} + +} + + +/// Adds pattern-matching-related methods to [GetWifiNetworksResponseModel]. +extension GetWifiNetworksResponseModelPatterns on GetWifiNetworksResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _GetWifiNetworksResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _GetWifiNetworksResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _GetWifiNetworksResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _GetWifiNetworksResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _GetWifiNetworksResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _GetWifiNetworksResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int total, List items)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _GetWifiNetworksResponseModel() when $default != null: +return $default(_that.total,_that.items);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int total, List items) $default,) {final _that = this; +switch (_that) { +case _GetWifiNetworksResponseModel(): +return $default(_that.total,_that.items);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int total, List items)? $default,) {final _that = this; +switch (_that) { +case _GetWifiNetworksResponseModel() when $default != null: +return $default(_that.total,_that.items);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _GetWifiNetworksResponseModel implements GetWifiNetworksResponseModel { + const _GetWifiNetworksResponseModel({required this.total, required final List items}): _items = items; + factory _GetWifiNetworksResponseModel.fromJson(Map json) => _$GetWifiNetworksResponseModelFromJson(json); + +@override final int total; + final List _items; +@override List get items { + if (_items is EqualUnmodifiableListView) return _items; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_items); +} + + +/// Create a copy of GetWifiNetworksResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$GetWifiNetworksResponseModelCopyWith<_GetWifiNetworksResponseModel> get copyWith => __$GetWifiNetworksResponseModelCopyWithImpl<_GetWifiNetworksResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$GetWifiNetworksResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetWifiNetworksResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other._items, _items)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(_items)); + +@override +String toString() { + return 'GetWifiNetworksResponseModel(total: $total, items: $items)'; +} + + +} + +/// @nodoc +abstract mixin class _$GetWifiNetworksResponseModelCopyWith<$Res> implements $GetWifiNetworksResponseModelCopyWith<$Res> { + factory _$GetWifiNetworksResponseModelCopyWith(_GetWifiNetworksResponseModel value, $Res Function(_GetWifiNetworksResponseModel) _then) = __$GetWifiNetworksResponseModelCopyWithImpl; +@override @useResult +$Res call({ + int total, List items +}); + + + + +} +/// @nodoc +class __$GetWifiNetworksResponseModelCopyWithImpl<$Res> + implements _$GetWifiNetworksResponseModelCopyWith<$Res> { + __$GetWifiNetworksResponseModelCopyWithImpl(this._self, this._then); + + final _GetWifiNetworksResponseModel _self; + final $Res Function(_GetWifiNetworksResponseModel) _then; + +/// Create a copy of GetWifiNetworksResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? total = null,Object? items = null,}) { + return _then(_GetWifiNetworksResponseModel( +total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable +as int,items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable +as List, + )); +} + + +} + + +/// @nodoc +mixin _$WifiNetworkItemResponseModel { + + String get id; String get deviceId; String get ssid; String get bssid; int get createdAt; int? get updatedAt; +/// Create a copy of WifiNetworkItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$WifiNetworkItemResponseModelCopyWith get copyWith => _$WifiNetworkItemResponseModelCopyWithImpl(this as WifiNetworkItemResponseModel, _$identity); + + /// Serializes this WifiNetworkItemResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is WifiNetworkItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.ssid, ssid) || other.ssid == ssid)&&(identical(other.bssid, bssid) || other.bssid == bssid)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,ssid,bssid,createdAt,updatedAt); + +@override +String toString() { + return 'WifiNetworkItemResponseModel(id: $id, deviceId: $deviceId, ssid: $ssid, bssid: $bssid, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class $WifiNetworkItemResponseModelCopyWith<$Res> { + factory $WifiNetworkItemResponseModelCopyWith(WifiNetworkItemResponseModel value, $Res Function(WifiNetworkItemResponseModel) _then) = _$WifiNetworkItemResponseModelCopyWithImpl; +@useResult +$Res call({ + String id, String deviceId, String ssid, String bssid, int createdAt, int? updatedAt +}); + + + + +} +/// @nodoc +class _$WifiNetworkItemResponseModelCopyWithImpl<$Res> + implements $WifiNetworkItemResponseModelCopyWith<$Res> { + _$WifiNetworkItemResponseModelCopyWithImpl(this._self, this._then); + + final WifiNetworkItemResponseModel _self; + final $Res Function(WifiNetworkItemResponseModel) _then; + +/// Create a copy of WifiNetworkItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceId = null,Object? ssid = null,Object? bssid = null,Object? createdAt = null,Object? updatedAt = freezed,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,ssid: null == ssid ? _self.ssid : ssid // ignore: cast_nullable_to_non_nullable +as String,bssid: null == bssid ? _self.bssid : bssid // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [WifiNetworkItemResponseModel]. +extension WifiNetworkItemResponseModelPatterns on WifiNetworkItemResponseModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _WifiNetworkItemResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _WifiNetworkItemResponseModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _WifiNetworkItemResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _WifiNetworkItemResponseModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _WifiNetworkItemResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _WifiNetworkItemResponseModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceId, String ssid, String bssid, int createdAt, int? updatedAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _WifiNetworkItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.ssid,_that.bssid,_that.createdAt,_that.updatedAt);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String deviceId, String ssid, String bssid, int createdAt, int? updatedAt) $default,) {final _that = this; +switch (_that) { +case _WifiNetworkItemResponseModel(): +return $default(_that.id,_that.deviceId,_that.ssid,_that.bssid,_that.createdAt,_that.updatedAt);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceId, String ssid, String bssid, int createdAt, int? updatedAt)? $default,) {final _that = this; +switch (_that) { +case _WifiNetworkItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceId,_that.ssid,_that.bssid,_that.createdAt,_that.updatedAt);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _WifiNetworkItemResponseModel implements WifiNetworkItemResponseModel { + const _WifiNetworkItemResponseModel({required this.id, required this.deviceId, required this.ssid, required this.bssid, required this.createdAt, this.updatedAt}); + factory _WifiNetworkItemResponseModel.fromJson(Map json) => _$WifiNetworkItemResponseModelFromJson(json); + +@override final String id; +@override final String deviceId; +@override final String ssid; +@override final String bssid; +@override final int createdAt; +@override final int? updatedAt; + +/// Create a copy of WifiNetworkItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$WifiNetworkItemResponseModelCopyWith<_WifiNetworkItemResponseModel> get copyWith => __$WifiNetworkItemResponseModelCopyWithImpl<_WifiNetworkItemResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$WifiNetworkItemResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _WifiNetworkItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.ssid, ssid) || other.ssid == ssid)&&(identical(other.bssid, bssid) || other.bssid == bssid)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceId,ssid,bssid,createdAt,updatedAt); + +@override +String toString() { + return 'WifiNetworkItemResponseModel(id: $id, deviceId: $deviceId, ssid: $ssid, bssid: $bssid, createdAt: $createdAt, updatedAt: $updatedAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$WifiNetworkItemResponseModelCopyWith<$Res> implements $WifiNetworkItemResponseModelCopyWith<$Res> { + factory _$WifiNetworkItemResponseModelCopyWith(_WifiNetworkItemResponseModel value, $Res Function(_WifiNetworkItemResponseModel) _then) = __$WifiNetworkItemResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceId, String ssid, String bssid, int createdAt, int? updatedAt +}); + + + + +} +/// @nodoc +class __$WifiNetworkItemResponseModelCopyWithImpl<$Res> + implements _$WifiNetworkItemResponseModelCopyWith<$Res> { + __$WifiNetworkItemResponseModelCopyWithImpl(this._self, this._then); + + final _WifiNetworkItemResponseModel _self; + final $Res Function(_WifiNetworkItemResponseModel) _then; + +/// Create a copy of WifiNetworkItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceId = null,Object? ssid = null,Object? bssid = null,Object? createdAt = null,Object? updatedAt = freezed,}) { + return _then(_WifiNetworkItemResponseModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,ssid: null == ssid ? _self.ssid : ssid // ignore: cast_nullable_to_non_nullable +as String,bssid: null == bssid ? _self.bssid : bssid // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/get_wifi_networks_response_model.g.dart b/modules/legacy/modules/settings/lib/src/core/data/models/get_wifi_networks_response_model.g.dart new file mode 100644 index 00000000..d489a226 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/get_wifi_networks_response_model.g.dart @@ -0,0 +1,44 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_wifi_networks_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_GetWifiNetworksResponseModel _$GetWifiNetworksResponseModelFromJson( + Map json, +) => _GetWifiNetworksResponseModel( + total: (json['total'] as num).toInt(), + items: (json['items'] as List) + .map( + (e) => WifiNetworkItemResponseModel.fromJson(e as Map), + ) + .toList(), +); + +Map _$GetWifiNetworksResponseModelToJson( + _GetWifiNetworksResponseModel instance, +) => {'total': instance.total, 'items': instance.items}; + +_WifiNetworkItemResponseModel _$WifiNetworkItemResponseModelFromJson( + Map json, +) => _WifiNetworkItemResponseModel( + id: json['id'] as String, + deviceId: json['deviceId'] as String, + ssid: json['ssid'] as String, + bssid: json['bssid'] as String, + createdAt: (json['createdAt'] as num).toInt(), + updatedAt: (json['updatedAt'] as num?)?.toInt(), +); + +Map _$WifiNetworkItemResponseModelToJson( + _WifiNetworkItemResponseModel instance, +) => { + 'id': instance.id, + 'deviceId': instance.deviceId, + 'ssid': instance.ssid, + 'bssid': instance.bssid, + 'createdAt': instance.createdAt, + 'updatedAt': instance.updatedAt, +}; diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/update_alarm_request_model.dart b/modules/legacy/modules/settings/lib/src/core/data/models/update_alarm_request_model.dart new file mode 100644 index 00000000..9f05de88 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/update_alarm_request_model.dart @@ -0,0 +1,17 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'update_alarm_request_model.freezed.dart'; +part 'update_alarm_request_model.g.dart'; + +@freezed +abstract class UpdateAlarmRequestModel with _$UpdateAlarmRequestModel { + const factory UpdateAlarmRequestModel({ + required String deviceId, + required String time, + required String message, + required int order, + }) = _UpdateAlarmRequestModel; + + factory UpdateAlarmRequestModel.fromJson(Map json) => + _$UpdateAlarmRequestModelFromJson(json); +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/update_alarm_request_model.freezed.dart b/modules/legacy/modules/settings/lib/src/core/data/models/update_alarm_request_model.freezed.dart new file mode 100644 index 00000000..8dabf363 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/update_alarm_request_model.freezed.dart @@ -0,0 +1,286 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'update_alarm_request_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$UpdateAlarmRequestModel { + + String get deviceId; String get time; String get message; int get order; +/// Create a copy of UpdateAlarmRequestModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$UpdateAlarmRequestModelCopyWith get copyWith => _$UpdateAlarmRequestModelCopyWithImpl(this as UpdateAlarmRequestModel, _$identity); + + /// Serializes this UpdateAlarmRequestModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is UpdateAlarmRequestModel&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.time, time) || other.time == time)&&(identical(other.message, message) || other.message == message)&&(identical(other.order, order) || other.order == order)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,deviceId,time,message,order); + +@override +String toString() { + return 'UpdateAlarmRequestModel(deviceId: $deviceId, time: $time, message: $message, order: $order)'; +} + + +} + +/// @nodoc +abstract mixin class $UpdateAlarmRequestModelCopyWith<$Res> { + factory $UpdateAlarmRequestModelCopyWith(UpdateAlarmRequestModel value, $Res Function(UpdateAlarmRequestModel) _then) = _$UpdateAlarmRequestModelCopyWithImpl; +@useResult +$Res call({ + String deviceId, String time, String message, int order +}); + + + + +} +/// @nodoc +class _$UpdateAlarmRequestModelCopyWithImpl<$Res> + implements $UpdateAlarmRequestModelCopyWith<$Res> { + _$UpdateAlarmRequestModelCopyWithImpl(this._self, this._then); + + final UpdateAlarmRequestModel _self; + final $Res Function(UpdateAlarmRequestModel) _then; + +/// Create a copy of UpdateAlarmRequestModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? deviceId = null,Object? time = null,Object? message = null,Object? order = null,}) { + return _then(_self.copyWith( +deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,time: null == time ? _self.time : time // ignore: cast_nullable_to_non_nullable +as String,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,order: null == order ? _self.order : order // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [UpdateAlarmRequestModel]. +extension UpdateAlarmRequestModelPatterns on UpdateAlarmRequestModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _UpdateAlarmRequestModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _UpdateAlarmRequestModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _UpdateAlarmRequestModel value) $default,){ +final _that = this; +switch (_that) { +case _UpdateAlarmRequestModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _UpdateAlarmRequestModel value)? $default,){ +final _that = this; +switch (_that) { +case _UpdateAlarmRequestModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String deviceId, String time, String message, int order)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _UpdateAlarmRequestModel() when $default != null: +return $default(_that.deviceId,_that.time,_that.message,_that.order);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String deviceId, String time, String message, int order) $default,) {final _that = this; +switch (_that) { +case _UpdateAlarmRequestModel(): +return $default(_that.deviceId,_that.time,_that.message,_that.order);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String deviceId, String time, String message, int order)? $default,) {final _that = this; +switch (_that) { +case _UpdateAlarmRequestModel() when $default != null: +return $default(_that.deviceId,_that.time,_that.message,_that.order);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _UpdateAlarmRequestModel implements UpdateAlarmRequestModel { + const _UpdateAlarmRequestModel({required this.deviceId, required this.time, required this.message, required this.order}); + factory _UpdateAlarmRequestModel.fromJson(Map json) => _$UpdateAlarmRequestModelFromJson(json); + +@override final String deviceId; +@override final String time; +@override final String message; +@override final int order; + +/// Create a copy of UpdateAlarmRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$UpdateAlarmRequestModelCopyWith<_UpdateAlarmRequestModel> get copyWith => __$UpdateAlarmRequestModelCopyWithImpl<_UpdateAlarmRequestModel>(this, _$identity); + +@override +Map toJson() { + return _$UpdateAlarmRequestModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _UpdateAlarmRequestModel&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.time, time) || other.time == time)&&(identical(other.message, message) || other.message == message)&&(identical(other.order, order) || other.order == order)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,deviceId,time,message,order); + +@override +String toString() { + return 'UpdateAlarmRequestModel(deviceId: $deviceId, time: $time, message: $message, order: $order)'; +} + + +} + +/// @nodoc +abstract mixin class _$UpdateAlarmRequestModelCopyWith<$Res> implements $UpdateAlarmRequestModelCopyWith<$Res> { + factory _$UpdateAlarmRequestModelCopyWith(_UpdateAlarmRequestModel value, $Res Function(_UpdateAlarmRequestModel) _then) = __$UpdateAlarmRequestModelCopyWithImpl; +@override @useResult +$Res call({ + String deviceId, String time, String message, int order +}); + + + + +} +/// @nodoc +class __$UpdateAlarmRequestModelCopyWithImpl<$Res> + implements _$UpdateAlarmRequestModelCopyWith<$Res> { + __$UpdateAlarmRequestModelCopyWithImpl(this._self, this._then); + + final _UpdateAlarmRequestModel _self; + final $Res Function(_UpdateAlarmRequestModel) _then; + +/// Create a copy of UpdateAlarmRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? deviceId = null,Object? time = null,Object? message = null,Object? order = null,}) { + return _then(_UpdateAlarmRequestModel( +deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,time: null == time ? _self.time : time // ignore: cast_nullable_to_non_nullable +as String,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,order: null == order ? _self.order : order // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/update_alarm_request_model.g.dart b/modules/legacy/modules/settings/lib/src/core/data/models/update_alarm_request_model.g.dart new file mode 100644 index 00000000..4df6ffca --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/update_alarm_request_model.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'update_alarm_request_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_UpdateAlarmRequestModel _$UpdateAlarmRequestModelFromJson( + Map json, +) => _UpdateAlarmRequestModel( + deviceId: json['deviceId'] as String, + time: json['time'] as String, + message: json['message'] as String, + order: (json['order'] as num).toInt(), +); + +Map _$UpdateAlarmRequestModelToJson( + _UpdateAlarmRequestModel instance, +) => { + 'deviceId': instance.deviceId, + 'time': instance.time, + 'message': instance.message, + 'order': instance.order, +}; diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/upsert_contact_list_request_model.dart b/modules/legacy/modules/settings/lib/src/core/data/models/upsert_contact_list_request_model.dart new file mode 100644 index 00000000..dd3bb082 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/upsert_contact_list_request_model.dart @@ -0,0 +1,30 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'upsert_contact_list_request_model.freezed.dart'; +part 'upsert_contact_list_request_model.g.dart'; + +@freezed +abstract class UpsertContactListRequestModel + with _$UpsertContactListRequestModel { + const factory UpsertContactListRequestModel({ + required String userId, + required String deviceId, + required String type, + required List contacts, + }) = _UpsertContactListRequestModel; + + factory UpsertContactListRequestModel.fromJson(Map json) => + _$UpsertContactListRequestModelFromJson(json); +} + +@freezed +abstract class UpsertContactListContactModel + with _$UpsertContactListContactModel { + const factory UpsertContactListContactModel({ + required String name, + required String phone, + }) = _UpsertContactListContactModel; + + factory UpsertContactListContactModel.fromJson(Map json) => + _$UpsertContactListContactModelFromJson(json); +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/upsert_contact_list_request_model.freezed.dart b/modules/legacy/modules/settings/lib/src/core/data/models/upsert_contact_list_request_model.freezed.dart new file mode 100644 index 00000000..ff73bacb --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/upsert_contact_list_request_model.freezed.dart @@ -0,0 +1,558 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'upsert_contact_list_request_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$UpsertContactListRequestModel { + + String get userId; String get deviceId; String get type; List get contacts; +/// Create a copy of UpsertContactListRequestModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$UpsertContactListRequestModelCopyWith get copyWith => _$UpsertContactListRequestModelCopyWithImpl(this as UpsertContactListRequestModel, _$identity); + + /// Serializes this UpsertContactListRequestModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is UpsertContactListRequestModel&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.contacts, contacts)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,userId,deviceId,type,const DeepCollectionEquality().hash(contacts)); + +@override +String toString() { + return 'UpsertContactListRequestModel(userId: $userId, deviceId: $deviceId, type: $type, contacts: $contacts)'; +} + + +} + +/// @nodoc +abstract mixin class $UpsertContactListRequestModelCopyWith<$Res> { + factory $UpsertContactListRequestModelCopyWith(UpsertContactListRequestModel value, $Res Function(UpsertContactListRequestModel) _then) = _$UpsertContactListRequestModelCopyWithImpl; +@useResult +$Res call({ + String userId, String deviceId, String type, List contacts +}); + + + + +} +/// @nodoc +class _$UpsertContactListRequestModelCopyWithImpl<$Res> + implements $UpsertContactListRequestModelCopyWith<$Res> { + _$UpsertContactListRequestModelCopyWithImpl(this._self, this._then); + + final UpsertContactListRequestModel _self; + final $Res Function(UpsertContactListRequestModel) _then; + +/// Create a copy of UpsertContactListRequestModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? userId = null,Object? deviceId = null,Object? type = null,Object? contacts = null,}) { + return _then(_self.copyWith( +userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable +as String,contacts: null == contacts ? _self.contacts : contacts // ignore: cast_nullable_to_non_nullable +as List, + )); +} + +} + + +/// Adds pattern-matching-related methods to [UpsertContactListRequestModel]. +extension UpsertContactListRequestModelPatterns on UpsertContactListRequestModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _UpsertContactListRequestModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _UpsertContactListRequestModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _UpsertContactListRequestModel value) $default,){ +final _that = this; +switch (_that) { +case _UpsertContactListRequestModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _UpsertContactListRequestModel value)? $default,){ +final _that = this; +switch (_that) { +case _UpsertContactListRequestModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String userId, String deviceId, String type, List contacts)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _UpsertContactListRequestModel() when $default != null: +return $default(_that.userId,_that.deviceId,_that.type,_that.contacts);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String userId, String deviceId, String type, List contacts) $default,) {final _that = this; +switch (_that) { +case _UpsertContactListRequestModel(): +return $default(_that.userId,_that.deviceId,_that.type,_that.contacts);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String userId, String deviceId, String type, List contacts)? $default,) {final _that = this; +switch (_that) { +case _UpsertContactListRequestModel() when $default != null: +return $default(_that.userId,_that.deviceId,_that.type,_that.contacts);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _UpsertContactListRequestModel implements UpsertContactListRequestModel { + const _UpsertContactListRequestModel({required this.userId, required this.deviceId, required this.type, required final List contacts}): _contacts = contacts; + factory _UpsertContactListRequestModel.fromJson(Map json) => _$UpsertContactListRequestModelFromJson(json); + +@override final String userId; +@override final String deviceId; +@override final String type; + final List _contacts; +@override List get contacts { + if (_contacts is EqualUnmodifiableListView) return _contacts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_contacts); +} + + +/// Create a copy of UpsertContactListRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$UpsertContactListRequestModelCopyWith<_UpsertContactListRequestModel> get copyWith => __$UpsertContactListRequestModelCopyWithImpl<_UpsertContactListRequestModel>(this, _$identity); + +@override +Map toJson() { + return _$UpsertContactListRequestModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _UpsertContactListRequestModel&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._contacts, _contacts)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,userId,deviceId,type,const DeepCollectionEquality().hash(_contacts)); + +@override +String toString() { + return 'UpsertContactListRequestModel(userId: $userId, deviceId: $deviceId, type: $type, contacts: $contacts)'; +} + + +} + +/// @nodoc +abstract mixin class _$UpsertContactListRequestModelCopyWith<$Res> implements $UpsertContactListRequestModelCopyWith<$Res> { + factory _$UpsertContactListRequestModelCopyWith(_UpsertContactListRequestModel value, $Res Function(_UpsertContactListRequestModel) _then) = __$UpsertContactListRequestModelCopyWithImpl; +@override @useResult +$Res call({ + String userId, String deviceId, String type, List contacts +}); + + + + +} +/// @nodoc +class __$UpsertContactListRequestModelCopyWithImpl<$Res> + implements _$UpsertContactListRequestModelCopyWith<$Res> { + __$UpsertContactListRequestModelCopyWithImpl(this._self, this._then); + + final _UpsertContactListRequestModel _self; + final $Res Function(_UpsertContactListRequestModel) _then; + +/// Create a copy of UpsertContactListRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? userId = null,Object? deviceId = null,Object? type = null,Object? contacts = null,}) { + return _then(_UpsertContactListRequestModel( +userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable +as String,contacts: null == contacts ? _self._contacts : contacts // ignore: cast_nullable_to_non_nullable +as List, + )); +} + + +} + + +/// @nodoc +mixin _$UpsertContactListContactModel { + + String get name; String get phone; +/// Create a copy of UpsertContactListContactModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$UpsertContactListContactModelCopyWith get copyWith => _$UpsertContactListContactModelCopyWithImpl(this as UpsertContactListContactModel, _$identity); + + /// Serializes this UpsertContactListContactModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is UpsertContactListContactModel&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,name,phone); + +@override +String toString() { + return 'UpsertContactListContactModel(name: $name, phone: $phone)'; +} + + +} + +/// @nodoc +abstract mixin class $UpsertContactListContactModelCopyWith<$Res> { + factory $UpsertContactListContactModelCopyWith(UpsertContactListContactModel value, $Res Function(UpsertContactListContactModel) _then) = _$UpsertContactListContactModelCopyWithImpl; +@useResult +$Res call({ + String name, String phone +}); + + + + +} +/// @nodoc +class _$UpsertContactListContactModelCopyWithImpl<$Res> + implements $UpsertContactListContactModelCopyWith<$Res> { + _$UpsertContactListContactModelCopyWithImpl(this._self, this._then); + + final UpsertContactListContactModel _self; + final $Res Function(UpsertContactListContactModel) _then; + +/// Create a copy of UpsertContactListContactModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? name = null,Object? phone = null,}) { + return _then(_self.copyWith( +name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [UpsertContactListContactModel]. +extension UpsertContactListContactModelPatterns on UpsertContactListContactModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _UpsertContactListContactModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _UpsertContactListContactModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _UpsertContactListContactModel value) $default,){ +final _that = this; +switch (_that) { +case _UpsertContactListContactModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _UpsertContactListContactModel value)? $default,){ +final _that = this; +switch (_that) { +case _UpsertContactListContactModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String name, String phone)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _UpsertContactListContactModel() when $default != null: +return $default(_that.name,_that.phone);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String name, String phone) $default,) {final _that = this; +switch (_that) { +case _UpsertContactListContactModel(): +return $default(_that.name,_that.phone);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String name, String phone)? $default,) {final _that = this; +switch (_that) { +case _UpsertContactListContactModel() when $default != null: +return $default(_that.name,_that.phone);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _UpsertContactListContactModel implements UpsertContactListContactModel { + const _UpsertContactListContactModel({required this.name, required this.phone}); + factory _UpsertContactListContactModel.fromJson(Map json) => _$UpsertContactListContactModelFromJson(json); + +@override final String name; +@override final String phone; + +/// Create a copy of UpsertContactListContactModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$UpsertContactListContactModelCopyWith<_UpsertContactListContactModel> get copyWith => __$UpsertContactListContactModelCopyWithImpl<_UpsertContactListContactModel>(this, _$identity); + +@override +Map toJson() { + return _$UpsertContactListContactModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _UpsertContactListContactModel&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,name,phone); + +@override +String toString() { + return 'UpsertContactListContactModel(name: $name, phone: $phone)'; +} + + +} + +/// @nodoc +abstract mixin class _$UpsertContactListContactModelCopyWith<$Res> implements $UpsertContactListContactModelCopyWith<$Res> { + factory _$UpsertContactListContactModelCopyWith(_UpsertContactListContactModel value, $Res Function(_UpsertContactListContactModel) _then) = __$UpsertContactListContactModelCopyWithImpl; +@override @useResult +$Res call({ + String name, String phone +}); + + + + +} +/// @nodoc +class __$UpsertContactListContactModelCopyWithImpl<$Res> + implements _$UpsertContactListContactModelCopyWith<$Res> { + __$UpsertContactListContactModelCopyWithImpl(this._self, this._then); + + final _UpsertContactListContactModel _self; + final $Res Function(_UpsertContactListContactModel) _then; + +/// Create a copy of UpsertContactListContactModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? name = null,Object? phone = null,}) { + return _then(_UpsertContactListContactModel( +name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/settings/lib/src/core/data/models/upsert_contact_list_request_model.g.dart b/modules/legacy/modules/settings/lib/src/core/data/models/upsert_contact_list_request_model.g.dart new file mode 100644 index 00000000..19346cd2 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/models/upsert_contact_list_request_model.g.dart @@ -0,0 +1,41 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'upsert_contact_list_request_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_UpsertContactListRequestModel _$UpsertContactListRequestModelFromJson( + Map json, +) => _UpsertContactListRequestModel( + userId: json['userId'] as String, + deviceId: json['deviceId'] as String, + type: json['type'] as String, + contacts: (json['contacts'] as List) + .map( + (e) => + UpsertContactListContactModel.fromJson(e as Map), + ) + .toList(), +); + +Map _$UpsertContactListRequestModelToJson( + _UpsertContactListRequestModel instance, +) => { + 'userId': instance.userId, + 'deviceId': instance.deviceId, + 'type': instance.type, + 'contacts': instance.contacts, +}; + +_UpsertContactListContactModel _$UpsertContactListContactModelFromJson( + Map json, +) => _UpsertContactListContactModel( + name: json['name'] as String, + phone: json['phone'] as String, +); + +Map _$UpsertContactListContactModelToJson( + _UpsertContactListContactModel instance, +) => {'name': instance.name, 'phone': instance.phone}; diff --git a/modules/legacy/modules/settings/lib/src/core/data/repositories/alarm_repository_impl.dart b/modules/legacy/modules/settings/lib/src/core/data/repositories/alarm_repository_impl.dart new file mode 100644 index 00000000..e7fcf6e8 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/repositories/alarm_repository_impl.dart @@ -0,0 +1,36 @@ +import 'package:settings/src/core/data/datasources/alarm_remote_datasource.dart'; +import 'package:settings/src/core/data/models/create_alarm_request_model.dart'; +import 'package:settings/src/core/data/models/get_alarms_response_model.dart'; +import 'package:settings/src/core/data/models/update_alarm_request_model.dart'; +import 'package:settings/src/core/domain/repositories/alarm_repository.dart'; +import 'package:settings/src/features/alarm/domain/entities/alarm_entity.dart'; + +class AlarmRepositoryImpl implements AlarmRepository { + const AlarmRepositoryImpl(this._remote); + + final AlarmRemoteDatasource _remote; + + @override + Future> getAlarms({required String deviceId}) async { + final response = await _remote.getAlarms(deviceId: deviceId); + return response.toEntity(); + } + + @override + Future createAlarm({required CreateAlarmRequestModel request}) { + return _remote.createAlarm(request: request); + } + + @override + Future updateAlarm({ + required String alarmId, + required UpdateAlarmRequestModel request, + }) { + return _remote.updateAlarm(alarmId: alarmId, request: request); + } + + @override + Future deleteAlarm({required String alarmId}) { + return _remote.deleteAlarm(alarmId: alarmId); + } +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/repositories/block_phone_repository_impl.dart b/modules/legacy/modules/settings/lib/src/core/data/repositories/block_phone_repository_impl.dart new file mode 100644 index 00000000..21c15369 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/repositories/block_phone_repository_impl.dart @@ -0,0 +1,48 @@ +import 'package:settings/src/core/data/datasources/contact_lists_remote_datasource.dart'; +import 'package:settings/src/core/data/models/upsert_contact_list_request_model.dart'; +import 'package:settings/src/core/domain/entities/contact_list_contact_entity.dart'; +import 'package:settings/src/core/domain/repositories/block_phone_repository.dart'; + +class BlockPhoneRepositoryImpl implements BlockPhoneRepository { + BlockPhoneRepositoryImpl(this._datasource); + + final ContactListsRemoteDatasource _datasource; + + @override + Future> getWhitelist({ + required String deviceId, + }) async { + final response = await _datasource.getContactLists(deviceId: deviceId); + + final whiteList = response.items + .where((item) => item.type == 'white') + .firstOrNull; + + if (whiteList == null) return []; + + return whiteList.contacts + .map((c) => ContactListContactEntity(name: c.name, phone: c.phone)) + .toList(); + } + + @override + Future upsertWhitelist({ + required String userId, + required String deviceId, + required List contacts, + }) async { + final request = UpsertContactListRequestModel( + userId: userId, + deviceId: deviceId, + type: 'white', + contacts: contacts + .map( + (c) => + UpsertContactListContactModel(name: c.name, phone: c.phone), + ) + .toList(), + ); + + await _datasource.upsertContactList(request: request); + } +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/repositories/language_repository_impl.dart b/modules/legacy/modules/settings/lib/src/core/data/repositories/language_repository_impl.dart new file mode 100644 index 00000000..0e39c41b --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/repositories/language_repository_impl.dart @@ -0,0 +1,19 @@ +import 'package:settings/src/core/data/datasources/language_remote_datasource.dart'; +import 'package:settings/src/core/domain/repositories/language_repository.dart'; + +class LanguageRepositoryImpl implements LanguageRepository { + LanguageRepositoryImpl(this._datasource); + + final LanguageRemoteDatasource _datasource; + + @override + Future updateDeviceLanguage({ + required Map deviceData, + required String newLanguage, + }) async { + await _datasource.updateDeviceLanguage( + deviceData: deviceData, + newLanguage: newLanguage, + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/repositories/settings_repository_impl.dart b/modules/legacy/modules/settings/lib/src/core/data/repositories/settings_repository_impl.dart index c6a30bb1..f154d9a6 100644 --- a/modules/legacy/modules/settings/lib/src/core/data/repositories/settings_repository_impl.dart +++ b/modules/legacy/modules/settings/lib/src/core/data/repositories/settings_repository_impl.dart @@ -5,9 +5,4 @@ class SettingsRepositoryImpl implements SettingsRepository { const SettingsRepositoryImpl(this._remote); final SettingsRemoteDatasource _remote; - - /*@override - Future> getContacts({required String userId}) { - return _remote.getContacts(userId: userId); - }*/ } diff --git a/modules/legacy/modules/settings/lib/src/core/data/repositories/sos_contacts_repository_impl.dart b/modules/legacy/modules/settings/lib/src/core/data/repositories/sos_contacts_repository_impl.dart new file mode 100644 index 00000000..fff6f844 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/repositories/sos_contacts_repository_impl.dart @@ -0,0 +1,48 @@ +import 'package:settings/src/core/data/datasources/contact_lists_remote_datasource.dart'; +import 'package:settings/src/core/data/models/upsert_contact_list_request_model.dart'; +import 'package:settings/src/core/domain/entities/contact_list_contact_entity.dart'; +import 'package:settings/src/core/domain/repositories/sos_contacts_repository.dart'; + +class SosContactsRepositoryImpl implements SosContactsRepository { + SosContactsRepositoryImpl(this._datasource); + + final ContactListsRemoteDatasource _datasource; + + @override + Future> getEmergencyContacts({ + required String deviceId, + }) async { + final response = await _datasource.getContactLists(deviceId: deviceId); + + final emergencyList = response.items + .where((item) => item.type == 'emergency') + .firstOrNull; + + if (emergencyList == null) return []; + + return emergencyList.contacts + .map((c) => ContactListContactEntity(name: c.name, phone: c.phone)) + .toList(); + } + + @override + Future upsertEmergencyContacts({ + required String userId, + required String deviceId, + required List contacts, + }) async { + final request = UpsertContactListRequestModel( + userId: userId, + deviceId: deviceId, + type: 'emergency', + contacts: contacts + .map( + (c) => + UpsertContactListContactModel(name: c.name, phone: c.phone), + ) + .toList(), + ); + + await _datasource.upsertContactList(request: request); + } +} diff --git a/modules/legacy/modules/settings/lib/src/core/data/repositories/wifi_repository_impl.dart b/modules/legacy/modules/settings/lib/src/core/data/repositories/wifi_repository_impl.dart new file mode 100644 index 00000000..0d699a43 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/data/repositories/wifi_repository_impl.dart @@ -0,0 +1,52 @@ +import 'package:uuid/uuid.dart'; + +import '../../../features/wifi_settings/domain/entities/wifi_network_entity.dart'; +import '../../domain/repositories/wifi_repository.dart'; +import '../datasources/wifi_remote_datasource.dart'; +import '../models/create_wifi_network_request_model.dart'; + +class WifiRepositoryImpl implements WifiRepository { + WifiRepositoryImpl(this._datasource); + + static const _uuid = Uuid(); + final WifiRemoteDatasource _datasource; + + @override + Future> getWifiNetworks({ + required String deviceId, + }) async { + final response = + await _datasource.getWifiNetworks(deviceId: deviceId); + + return response.items + .map( + (item) => WifiNetworkEntity( + id: item.id, + ssid: item.ssid, + bssid: item.bssid, + ), + ) + .toList(); + } + + @override + Future createWifiNetwork({ + required String deviceId, + required String ssid, + required String bssid, + }) async { + final request = CreateWifiNetworkRequestModel( + id: _uuid.v4(), + deviceId: deviceId, + ssid: ssid, + bssid: bssid, + ); + + await _datasource.createWifiNetwork(request: request); + } + + @override + Future deleteWifiNetwork({required String networkId}) { + return _datasource.deleteWifiNetwork(networkId: networkId); + } +} diff --git a/modules/legacy/modules/settings/lib/src/core/domain/entities/contact_list_contact_entity.dart b/modules/legacy/modules/settings/lib/src/core/domain/entities/contact_list_contact_entity.dart new file mode 100644 index 00000000..6ea774ee --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/domain/entities/contact_list_contact_entity.dart @@ -0,0 +1,11 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'contact_list_contact_entity.freezed.dart'; + +@freezed +abstract class ContactListContactEntity with _$ContactListContactEntity { + const factory ContactListContactEntity({ + required String name, + required String phone, + }) = _ContactListContactEntity; +} diff --git a/modules/legacy/modules/settings/lib/src/core/domain/entities/contact_list_contact_entity.freezed.dart b/modules/legacy/modules/settings/lib/src/core/domain/entities/contact_list_contact_entity.freezed.dart new file mode 100644 index 00000000..16c815da --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/domain/entities/contact_list_contact_entity.freezed.dart @@ -0,0 +1,274 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'contact_list_contact_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$ContactListContactEntity { + + String get name; String get phone; +/// Create a copy of ContactListContactEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ContactListContactEntityCopyWith get copyWith => _$ContactListContactEntityCopyWithImpl(this as ContactListContactEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ContactListContactEntity&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)); +} + + +@override +int get hashCode => Object.hash(runtimeType,name,phone); + +@override +String toString() { + return 'ContactListContactEntity(name: $name, phone: $phone)'; +} + + +} + +/// @nodoc +abstract mixin class $ContactListContactEntityCopyWith<$Res> { + factory $ContactListContactEntityCopyWith(ContactListContactEntity value, $Res Function(ContactListContactEntity) _then) = _$ContactListContactEntityCopyWithImpl; +@useResult +$Res call({ + String name, String phone +}); + + + + +} +/// @nodoc +class _$ContactListContactEntityCopyWithImpl<$Res> + implements $ContactListContactEntityCopyWith<$Res> { + _$ContactListContactEntityCopyWithImpl(this._self, this._then); + + final ContactListContactEntity _self; + final $Res Function(ContactListContactEntity) _then; + +/// Create a copy of ContactListContactEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? name = null,Object? phone = null,}) { + return _then(_self.copyWith( +name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [ContactListContactEntity]. +extension ContactListContactEntityPatterns on ContactListContactEntity { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _ContactListContactEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _ContactListContactEntity() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _ContactListContactEntity value) $default,){ +final _that = this; +switch (_that) { +case _ContactListContactEntity(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ContactListContactEntity value)? $default,){ +final _that = this; +switch (_that) { +case _ContactListContactEntity() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String name, String phone)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _ContactListContactEntity() when $default != null: +return $default(_that.name,_that.phone);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String name, String phone) $default,) {final _that = this; +switch (_that) { +case _ContactListContactEntity(): +return $default(_that.name,_that.phone);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String name, String phone)? $default,) {final _that = this; +switch (_that) { +case _ContactListContactEntity() when $default != null: +return $default(_that.name,_that.phone);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _ContactListContactEntity implements ContactListContactEntity { + const _ContactListContactEntity({required this.name, required this.phone}); + + +@override final String name; +@override final String phone; + +/// Create a copy of ContactListContactEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ContactListContactEntityCopyWith<_ContactListContactEntity> get copyWith => __$ContactListContactEntityCopyWithImpl<_ContactListContactEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ContactListContactEntity&&(identical(other.name, name) || other.name == name)&&(identical(other.phone, phone) || other.phone == phone)); +} + + +@override +int get hashCode => Object.hash(runtimeType,name,phone); + +@override +String toString() { + return 'ContactListContactEntity(name: $name, phone: $phone)'; +} + + +} + +/// @nodoc +abstract mixin class _$ContactListContactEntityCopyWith<$Res> implements $ContactListContactEntityCopyWith<$Res> { + factory _$ContactListContactEntityCopyWith(_ContactListContactEntity value, $Res Function(_ContactListContactEntity) _then) = __$ContactListContactEntityCopyWithImpl; +@override @useResult +$Res call({ + String name, String phone +}); + + + + +} +/// @nodoc +class __$ContactListContactEntityCopyWithImpl<$Res> + implements _$ContactListContactEntityCopyWith<$Res> { + __$ContactListContactEntityCopyWithImpl(this._self, this._then); + + final _ContactListContactEntity _self; + final $Res Function(_ContactListContactEntity) _then; + +/// Create a copy of ContactListContactEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? name = null,Object? phone = null,}) { + return _then(_ContactListContactEntity( +name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/settings/lib/src/core/domain/repositories/alarm_repository.dart b/modules/legacy/modules/settings/lib/src/core/domain/repositories/alarm_repository.dart new file mode 100644 index 00000000..916e0ab4 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/domain/repositories/alarm_repository.dart @@ -0,0 +1,13 @@ +import 'package:settings/src/core/data/models/create_alarm_request_model.dart'; +import 'package:settings/src/core/data/models/update_alarm_request_model.dart'; +import 'package:settings/src/features/alarm/domain/entities/alarm_entity.dart'; + +abstract class AlarmRepository { + Future> getAlarms({required String deviceId}); + Future createAlarm({required CreateAlarmRequestModel request}); + Future updateAlarm({ + required String alarmId, + required UpdateAlarmRequestModel request, + }); + Future deleteAlarm({required String alarmId}); +} diff --git a/modules/legacy/modules/settings/lib/src/core/domain/repositories/block_phone_repository.dart b/modules/legacy/modules/settings/lib/src/core/domain/repositories/block_phone_repository.dart new file mode 100644 index 00000000..a73a64ab --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/domain/repositories/block_phone_repository.dart @@ -0,0 +1,13 @@ +import 'package:settings/src/core/domain/entities/contact_list_contact_entity.dart'; + +abstract class BlockPhoneRepository { + Future> getWhitelist({ + required String deviceId, + }); + + Future upsertWhitelist({ + required String userId, + required String deviceId, + required List contacts, + }); +} diff --git a/modules/legacy/modules/settings/lib/src/core/domain/repositories/language_repository.dart b/modules/legacy/modules/settings/lib/src/core/domain/repositories/language_repository.dart new file mode 100644 index 00000000..79c782d4 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/domain/repositories/language_repository.dart @@ -0,0 +1,6 @@ +abstract class LanguageRepository { + Future updateDeviceLanguage({ + required Map deviceData, + required String newLanguage, + }); +} diff --git a/modules/legacy/modules/settings/lib/src/core/domain/repositories/settings_repository.dart b/modules/legacy/modules/settings/lib/src/core/domain/repositories/settings_repository.dart index 5d948c13..87051020 100644 --- a/modules/legacy/modules/settings/lib/src/core/domain/repositories/settings_repository.dart +++ b/modules/legacy/modules/settings/lib/src/core/domain/repositories/settings_repository.dart @@ -1,3 +1,2 @@ abstract class SettingsRepository { - // Future> getContacts({required String userId}); } diff --git a/modules/legacy/modules/settings/lib/src/core/domain/repositories/sos_contacts_repository.dart b/modules/legacy/modules/settings/lib/src/core/domain/repositories/sos_contacts_repository.dart new file mode 100644 index 00000000..c569dc33 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/domain/repositories/sos_contacts_repository.dart @@ -0,0 +1,13 @@ +import 'package:settings/src/core/domain/entities/contact_list_contact_entity.dart'; + +abstract class SosContactsRepository { + Future> getEmergencyContacts({ + required String deviceId, + }); + + Future upsertEmergencyContacts({ + required String userId, + required String deviceId, + required List contacts, + }); +} diff --git a/modules/legacy/modules/settings/lib/src/core/domain/repositories/wifi_repository.dart b/modules/legacy/modules/settings/lib/src/core/domain/repositories/wifi_repository.dart new file mode 100644 index 00000000..e6831bc5 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/domain/repositories/wifi_repository.dart @@ -0,0 +1,15 @@ +import 'package:settings/src/features/wifi_settings/domain/entities/wifi_network_entity.dart'; + +abstract class WifiRepository { + Future> getWifiNetworks({ + required String deviceId, + }); + + Future createWifiNetwork({ + required String deviceId, + required String ssid, + required String bssid, + }); + + Future deleteWifiNetwork({required String networkId}); +} diff --git a/modules/legacy/modules/settings/lib/src/core/presentation/widgets/contact_list_contact_card.dart b/modules/legacy/modules/settings/lib/src/core/presentation/widgets/contact_list_contact_card.dart new file mode 100644 index 00000000..855e65fc --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/presentation/widgets/contact_list_contact_card.dart @@ -0,0 +1,85 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:utils/utils.dart'; + +import '../../domain/entities/contact_list_contact_entity.dart'; + +class ContactListContactCard extends StatelessWidget { + final ContactListContactEntity contact; + final VoidCallback onDelete; + final ThemePort theme; + + const ContactListContactCard({ + super.key, + required this.contact, + required this.onDelete, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 10, big: 8), + ), + child: Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + vertical: SizeUtils.getByScreen(small: 14, big: 12), + ), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundSecondary), + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + child: Row( + children: [ + Icon( + Icons.person_outline, + color: theme.getColorFor(ThemeCode.legacyPrimary), + size: SizeUtils.getByScreen(small: 28, big: 30), + ), + SizedBox(width: SizeUtils.getByScreen(small: 12, big: 14)), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + contact.name, + style: TextStyle( + fontWeight: FontWeight.w600, + color: theme.getColorFor(ThemeCode.textPrimary), + fontSize: SizeUtils.getByScreen(small: 15, big: 16), + ), + ), + SizedBox(height: 2), + Text( + contact.phone, + style: TextStyle( + color: theme.getColorFor(ThemeCode.textPrimary) + .withAlpha(178), + fontSize: SizeUtils.getByScreen(small: 13, big: 14), + ), + ), + ], + ), + ), + InkWell( + onTap: onDelete, + borderRadius: BorderRadius.circular(8), + child: Padding( + padding: EdgeInsets.all( + SizeUtils.getByScreen(small: 6, big: 8), + ), + child: Icon( + Icons.delete_outline, + color: Colors.red, + size: SizeUtils.getByScreen(small: 22, big: 24), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/core/providers/alarm_remote_datasource_provider.dart b/modules/legacy/modules/settings/lib/src/core/providers/alarm_remote_datasource_provider.dart new file mode 100644 index 00000000..dc6391e0 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/providers/alarm_remote_datasource_provider.dart @@ -0,0 +1,9 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:settings/src/core/data/datasources/alarm_remote_datasource.dart'; +import 'package:settings/src/core/data/datasources/alarm_remote_datasource_impl.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +final alarmRemoteDatasourceProvider = Provider((ref) { + final questiaRepository = getIt(); + return AlarmRemoteDatasourceImpl(questiaRepository); +}); diff --git a/modules/legacy/modules/settings/lib/src/core/providers/alarm_repository_provider.dart b/modules/legacy/modules/settings/lib/src/core/providers/alarm_repository_provider.dart new file mode 100644 index 00000000..c7e864e2 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/providers/alarm_repository_provider.dart @@ -0,0 +1,9 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:settings/src/core/data/repositories/alarm_repository_impl.dart'; +import 'package:settings/src/core/domain/repositories/alarm_repository.dart'; +import 'package:settings/src/core/providers/alarm_remote_datasource_provider.dart'; + +final alarmRepositoryProvider = Provider((ref) { + final remote = ref.read(alarmRemoteDatasourceProvider); + return AlarmRepositoryImpl(remote); +}); diff --git a/modules/legacy/modules/settings/lib/src/core/providers/block_phone_repository_provider.dart b/modules/legacy/modules/settings/lib/src/core/providers/block_phone_repository_provider.dart new file mode 100644 index 00000000..f55ee52d --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/providers/block_phone_repository_provider.dart @@ -0,0 +1,9 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:settings/src/core/data/repositories/block_phone_repository_impl.dart'; +import 'package:settings/src/core/domain/repositories/block_phone_repository.dart'; +import 'package:settings/src/core/providers/contact_lists_remote_datasource_provider.dart'; + +final blockPhoneRepositoryProvider = Provider((ref) { + final remote = ref.read(contactListsRemoteDatasourceProvider); + return BlockPhoneRepositoryImpl(remote); +}); diff --git a/modules/legacy/modules/settings/lib/src/core/providers/contact_lists_remote_datasource_provider.dart b/modules/legacy/modules/settings/lib/src/core/providers/contact_lists_remote_datasource_provider.dart new file mode 100644 index 00000000..1fa50e3d --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/providers/contact_lists_remote_datasource_provider.dart @@ -0,0 +1,10 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:settings/src/core/data/datasources/contact_lists_remote_datasource.dart'; +import 'package:settings/src/core/data/datasources/contact_lists_remote_datasource_impl.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +final contactListsRemoteDatasourceProvider = + Provider((ref) { + final questiaRepository = getIt(); + return ContactListsRemoteDatasourceImpl(questiaRepository); +}); diff --git a/modules/legacy/modules/settings/lib/src/core/providers/language_remote_datasource_provider.dart b/modules/legacy/modules/settings/lib/src/core/providers/language_remote_datasource_provider.dart new file mode 100644 index 00000000..1a636862 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/providers/language_remote_datasource_provider.dart @@ -0,0 +1,10 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:settings/src/core/data/datasources/language_remote_datasource.dart'; +import 'package:settings/src/core/data/datasources/language_remote_datasource_impl.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +final languageRemoteDatasourceProvider = + Provider((ref) { + final questiaRepository = getIt(); + return LanguageRemoteDatasourceImpl(questiaRepository); +}); diff --git a/modules/legacy/modules/settings/lib/src/core/providers/language_repository_provider.dart b/modules/legacy/modules/settings/lib/src/core/providers/language_repository_provider.dart new file mode 100644 index 00000000..2c83eaa5 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/providers/language_repository_provider.dart @@ -0,0 +1,9 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:settings/src/core/data/repositories/language_repository_impl.dart'; +import 'package:settings/src/core/domain/repositories/language_repository.dart'; +import 'package:settings/src/core/providers/language_remote_datasource_provider.dart'; + +final languageRepositoryProvider = Provider((ref) { + final remote = ref.read(languageRemoteDatasourceProvider); + return LanguageRepositoryImpl(remote); +}); diff --git a/modules/legacy/modules/settings/lib/src/core/providers/sos_contacts_repository_provider.dart b/modules/legacy/modules/settings/lib/src/core/providers/sos_contacts_repository_provider.dart new file mode 100644 index 00000000..99d53400 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/providers/sos_contacts_repository_provider.dart @@ -0,0 +1,9 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:settings/src/core/data/repositories/sos_contacts_repository_impl.dart'; +import 'package:settings/src/core/domain/repositories/sos_contacts_repository.dart'; +import 'package:settings/src/core/providers/contact_lists_remote_datasource_provider.dart'; + +final sosContactsRepositoryProvider = Provider((ref) { + final remote = ref.read(contactListsRemoteDatasourceProvider); + return SosContactsRepositoryImpl(remote); +}); diff --git a/modules/legacy/modules/settings/lib/src/core/providers/wifi_remote_datasource_provider.dart b/modules/legacy/modules/settings/lib/src/core/providers/wifi_remote_datasource_provider.dart new file mode 100644 index 00000000..c0215f09 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/providers/wifi_remote_datasource_provider.dart @@ -0,0 +1,10 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:get_it/get_it.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +import '../data/datasources/wifi_remote_datasource.dart'; +import '../data/datasources/wifi_remote_datasource_impl.dart'; + +final wifiRemoteDatasourceProvider = Provider((ref) { + return WifiRemoteDatasourceImpl(GetIt.I()); +}); diff --git a/modules/legacy/modules/settings/lib/src/core/providers/wifi_repository_provider.dart b/modules/legacy/modules/settings/lib/src/core/providers/wifi_repository_provider.dart new file mode 100644 index 00000000..0dd7a20f --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/core/providers/wifi_repository_provider.dart @@ -0,0 +1,10 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../data/repositories/wifi_repository_impl.dart'; +import '../domain/repositories/wifi_repository.dart'; +import 'wifi_remote_datasource_provider.dart'; + +final wifiRepositoryProvider = Provider((ref) { + final remote = ref.read(wifiRemoteDatasourceProvider); + return WifiRepositoryImpl(remote); +}); diff --git a/modules/legacy/modules/settings/lib/src/features/alarm/domain/entities/alarm_entity.dart b/modules/legacy/modules/settings/lib/src/features/alarm/domain/entities/alarm_entity.dart index 2c029e74..a57f80b9 100644 --- a/modules/legacy/modules/settings/lib/src/features/alarm/domain/entities/alarm_entity.dart +++ b/modules/legacy/modules/settings/lib/src/features/alarm/domain/entities/alarm_entity.dart @@ -1,10 +1,82 @@ +import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'alarm_entity.freezed.dart'; +enum AlarmDateOption { once, daily, custom } + @freezed abstract class AlarmEntity with _$AlarmEntity { + const AlarmEntity._(); + const factory AlarmEntity({ required String id, + required String deviceId, + required TimeOfDay time, + required String message, + required int order, + required AlarmDateOption dateOption, + @Default([false, false, false, false, false, false, false]) + List days, + int? createdAt, + int? updatedAt, }) = _AlarmEntity; + + /// Encodes time + dateOption + days into API format: HH:MM-1-{type}[-XXXXXXX] + String get encodedTime { + final hh = time.hour.toString().padLeft(2, '0'); + final mm = time.minute.toString().padLeft(2, '0'); + + switch (dateOption) { + case AlarmDateOption.once: + return '$hh:$mm-1-1'; + case AlarmDateOption.daily: + return '$hh:$mm-1-2'; + case AlarmDateOption.custom: + final daysBits = days.map((d) => d ? '1' : '0').join(); + return '$hh:$mm-1-3-$daysBits'; + } + } + + /// Parses API time format: HH:MM-1-{type}[-XXXXXXX] + static ({TimeOfDay time, AlarmDateOption dateOption, List days}) + decodeTime(String raw) { + final parts = raw.split('-'); + final timeParts = parts[0].split(':'); + final time = TimeOfDay( + hour: int.parse(timeParts[0]), + minute: int.parse(timeParts[1]), + ); + + final type = int.parse(parts[2]); + + switch (type) { + case 1: + return ( + time: time, + dateOption: AlarmDateOption.once, + days: List.filled(7, false), + ); + case 2: + return ( + time: time, + dateOption: AlarmDateOption.daily, + days: List.filled(7, false), + ); + case 3: + final daysStr = parts[3]; + final days = List.generate(7, (i) => daysStr[i] == '1'); + return ( + time: time, + dateOption: AlarmDateOption.custom, + days: days, + ); + default: + return ( + time: time, + dateOption: AlarmDateOption.once, + days: List.filled(7, false), + ); + } + } } diff --git a/modules/legacy/modules/settings/lib/src/features/alarm/domain/entities/alarm_entity.freezed.dart b/modules/legacy/modules/settings/lib/src/features/alarm/domain/entities/alarm_entity.freezed.dart index 6dbd7dcd..e9dbafb8 100644 --- a/modules/legacy/modules/settings/lib/src/features/alarm/domain/entities/alarm_entity.freezed.dart +++ b/modules/legacy/modules/settings/lib/src/features/alarm/domain/entities/alarm_entity.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$AlarmEntity { - String get id; + String get id; String get deviceId; TimeOfDay get time; String get message; int get order; AlarmDateOption get dateOption; List get days; int? get createdAt; int? get updatedAt; /// Create a copy of AlarmEntity /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $AlarmEntityCopyWith get copyWith => _$AlarmEntityCopyWithImpl Object.hash(runtimeType,id); +int get hashCode => Object.hash(runtimeType,id,deviceId,time,message,order,dateOption,const DeepCollectionEquality().hash(days),createdAt,updatedAt); @override String toString() { - return 'AlarmEntity(id: $id)'; + return 'AlarmEntity(id: $id, deviceId: $deviceId, time: $time, message: $message, order: $order, dateOption: $dateOption, days: $days, createdAt: $createdAt, updatedAt: $updatedAt)'; } @@ -45,7 +45,7 @@ abstract mixin class $AlarmEntityCopyWith<$Res> { factory $AlarmEntityCopyWith(AlarmEntity value, $Res Function(AlarmEntity) _then) = _$AlarmEntityCopyWithImpl; @useResult $Res call({ - String id + String id, String deviceId, TimeOfDay time, String message, int order, AlarmDateOption dateOption, List days, int? createdAt, int? updatedAt }); @@ -62,10 +62,18 @@ class _$AlarmEntityCopyWithImpl<$Res> /// Create a copy of AlarmEntity /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceId = null,Object? time = null,Object? message = null,Object? order = null,Object? dateOption = null,Object? days = null,Object? createdAt = freezed,Object? updatedAt = freezed,}) { return _then(_self.copyWith( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String, +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,time: null == time ? _self.time : time // ignore: cast_nullable_to_non_nullable +as TimeOfDay,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,order: null == order ? _self.order : order // ignore: cast_nullable_to_non_nullable +as int,dateOption: null == dateOption ? _self.dateOption : dateOption // ignore: cast_nullable_to_non_nullable +as AlarmDateOption,days: null == days ? _self.days : days // ignore: cast_nullable_to_non_nullable +as List,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, )); } @@ -150,10 +158,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String id)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String deviceId, TimeOfDay time, String message, int order, AlarmDateOption dateOption, List days, int? createdAt, int? updatedAt)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _AlarmEntity() when $default != null: -return $default(_that.id);case _: +return $default(_that.id,_that.deviceId,_that.time,_that.message,_that.order,_that.dateOption,_that.days,_that.createdAt,_that.updatedAt);case _: return orElse(); } @@ -171,10 +179,10 @@ return $default(_that.id);case _: /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String id) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String id, String deviceId, TimeOfDay time, String message, int order, AlarmDateOption dateOption, List days, int? createdAt, int? updatedAt) $default,) {final _that = this; switch (_that) { case _AlarmEntity(): -return $default(_that.id);case _: +return $default(_that.id,_that.deviceId,_that.time,_that.message,_that.order,_that.dateOption,_that.days,_that.createdAt,_that.updatedAt);case _: throw StateError('Unexpected subclass'); } @@ -191,10 +199,10 @@ return $default(_that.id);case _: /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String deviceId, TimeOfDay time, String message, int order, AlarmDateOption dateOption, List days, int? createdAt, int? updatedAt)? $default,) {final _that = this; switch (_that) { case _AlarmEntity() when $default != null: -return $default(_that.id);case _: +return $default(_that.id,_that.deviceId,_that.time,_that.message,_that.order,_that.dateOption,_that.days,_that.createdAt,_that.updatedAt);case _: return null; } @@ -205,11 +213,25 @@ return $default(_that.id);case _: /// @nodoc -class _AlarmEntity implements AlarmEntity { - const _AlarmEntity({required this.id}); +class _AlarmEntity extends AlarmEntity { + const _AlarmEntity({required this.id, required this.deviceId, required this.time, required this.message, required this.order, required this.dateOption, final List days = const [false, false, false, false, false, false, false], this.createdAt, this.updatedAt}): _days = days,super._(); @override final String id; +@override final String deviceId; +@override final TimeOfDay time; +@override final String message; +@override final int order; +@override final AlarmDateOption dateOption; + final List _days; +@override@JsonKey() List get days { + if (_days is EqualUnmodifiableListView) return _days; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_days); +} + +@override final int? createdAt; +@override final int? updatedAt; /// Create a copy of AlarmEntity /// with the given fields replaced by the non-null parameter values. @@ -221,16 +243,16 @@ _$AlarmEntityCopyWith<_AlarmEntity> get copyWith => __$AlarmEntityCopyWithImpl<_ @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _AlarmEntity&&(identical(other.id, id) || other.id == id)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AlarmEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.time, time) || other.time == time)&&(identical(other.message, message) || other.message == message)&&(identical(other.order, order) || other.order == order)&&(identical(other.dateOption, dateOption) || other.dateOption == dateOption)&&const DeepCollectionEquality().equals(other._days, _days)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)); } @override -int get hashCode => Object.hash(runtimeType,id); +int get hashCode => Object.hash(runtimeType,id,deviceId,time,message,order,dateOption,const DeepCollectionEquality().hash(_days),createdAt,updatedAt); @override String toString() { - return 'AlarmEntity(id: $id)'; + return 'AlarmEntity(id: $id, deviceId: $deviceId, time: $time, message: $message, order: $order, dateOption: $dateOption, days: $days, createdAt: $createdAt, updatedAt: $updatedAt)'; } @@ -241,7 +263,7 @@ abstract mixin class _$AlarmEntityCopyWith<$Res> implements $AlarmEntityCopyWith factory _$AlarmEntityCopyWith(_AlarmEntity value, $Res Function(_AlarmEntity) _then) = __$AlarmEntityCopyWithImpl; @override @useResult $Res call({ - String id + String id, String deviceId, TimeOfDay time, String message, int order, AlarmDateOption dateOption, List days, int? createdAt, int? updatedAt }); @@ -258,10 +280,18 @@ class __$AlarmEntityCopyWithImpl<$Res> /// Create a copy of AlarmEntity /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceId = null,Object? time = null,Object? message = null,Object? order = null,Object? dateOption = null,Object? days = null,Object? createdAt = freezed,Object? updatedAt = freezed,}) { return _then(_AlarmEntity( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String, +as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable +as String,time: null == time ? _self.time : time // ignore: cast_nullable_to_non_nullable +as TimeOfDay,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,order: null == order ? _self.order : order // ignore: cast_nullable_to_non_nullable +as int,dateOption: null == dateOption ? _self.dateOption : dateOption // ignore: cast_nullable_to_non_nullable +as AlarmDateOption,days: null == days ? _self._days : days // ignore: cast_nullable_to_non_nullable +as List,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?, )); } diff --git a/modules/legacy/modules/settings/lib/src/features/alarm/domain/get_alarms_use_case.dart b/modules/legacy/modules/settings/lib/src/features/alarm/domain/get_alarms_use_case.dart deleted file mode 100644 index acda4007..00000000 --- a/modules/legacy/modules/settings/lib/src/features/alarm/domain/get_alarms_use_case.dart +++ /dev/null @@ -1,6 +0,0 @@ - -import 'package:settings/src/features/alarm/domain/entities/alarm_entity.dart'; - -abstract class GetAlarmsUseCase { - Future> getAlarms({required String deviceId}); -} diff --git a/modules/legacy/modules/settings/lib/src/features/alarm/domain/get_alarms_use_case_impl.dart b/modules/legacy/modules/settings/lib/src/features/alarm/domain/get_alarms_use_case_impl.dart deleted file mode 100644 index 5189c024..00000000 --- a/modules/legacy/modules/settings/lib/src/features/alarm/domain/get_alarms_use_case_impl.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:settings/src/core/domain/repositories/settings_repository.dart'; -import 'package:settings/src/features/alarm/domain/entities/alarm_entity.dart'; -import 'package:settings/src/features/alarm/domain/get_alarms_use_case.dart'; - -class GetAlarmsUseCaseImpl implements GetAlarmsUseCase { - GetAlarmsUseCaseImpl(this._repository); - - final SettingsRepository _repository; - - @override - Future> getAlarms({required String deviceId}) async { - return []; - // return _repository.getAlarms(deviceId: deviceId); - } -} diff --git a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/alarm_screen.dart b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/alarm_screen.dart index ab57a8a9..f830bcae 100644 --- a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/alarm_screen.dart +++ b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/alarm_screen.dart @@ -5,12 +5,12 @@ import 'package:legacy_shared/legacy_shared.dart'; import 'package:navigation/navigation.dart'; import 'package:settings/src/features/alarm/domain/entities/alarm_entity.dart'; import 'package:settings/src/features/alarm/presentation/state/alarm_view_model.dart'; +import 'package:settings/src/features/alarm/presentation/widgets/alarm_form_screen.dart' + show showAlarmForm; import 'package:sf_localizations/sf_localizations.dart'; - -import 'widgets/new_alarm_dialog.dart'; +import 'package:utils/utils.dart'; class AlarmScreen extends ConsumerWidget { - final NavigationContract navigationContract; const AlarmScreen({ @@ -20,133 +20,320 @@ class AlarmScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); + final theme = ref.watch(themePortProvider); + final state = ref.watch(alarmViewModelProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); - return LegacyPageLayout( - theme: theme, - title: context.translate(I18n.alarm), - body: Column( - children: [ - Center(child: - Icon(Icons.alarm_outlined, - color: theme.getColorFor(ThemeCode.legacyPrimary), - size: 240, - ) + ref.listen( + alarmViewModelProvider.select((s) => s.errorMessage), + (_, errorMessage) { + if (errorMessage.isNotEmpty) { + showTopSnackbar(context, message: errorMessage, type: MessageType.error); + } + }, + ); + + ref.listen( + alarmViewModelProvider.select((s) => s.successMessage), + (_, successMessage) { + if (successMessage.isNotEmpty) { + showTopSnackbar(context, message: context.translate(successMessage), type: MessageType.success); + ref.read(alarmViewModelProvider.notifier).clearSuccess(); + } + }, + ); + + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + surfaceTintColor: Colors.transparent, + elevation: 0, + centerTitle: true, + automaticallyImplyLeading: false, + leading: IconButton( + onPressed: () => navigationContract.goBack(), + icon: Icon( + Icons.adaptive.arrow_back, + color: primaryColor, + size: SizeUtils.getByScreen(small: 32, big: 28), ), - SizedBox(height: 36), - Text(context.translate(I18n.alarmsMessage), - textAlign: TextAlign.left, + ), + title: Text( + context.translate(I18n.alarm).toUpperCase(), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 19), + fontWeight: FontWeight.w500, + letterSpacing: 0, + color: primaryColor, ), - SizedBox(height: 36), - _AlarmsSection() + ), + actions: [ + if (state.alarms.length < 3) + Padding( + padding: EdgeInsets.only( + right: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: DecoratedBox( + decoration: BoxDecoration( + color: primaryColor, + shape: BoxShape.circle, + ), + child: IconButton( + onPressed: () => _openForm(context), + icon: Icon( + Icons.add, + color: Colors.white, + size: SizeUtils.getByScreen(small: 24, big: 22), + ), + ), + ), + ), ], - ) + ), + body: SafeArea( + top: false, + child: state.isLoading + ? const Center(child: CircularProgressIndicator()) + : state.alarms.isEmpty + ? _EmptyState(primaryColor: primaryColor) + : _AlarmList(onEdit: (alarm) => _openForm(context, alarm: alarm)), + ), + ); + } + + void _openForm(BuildContext context, {AlarmEntity? alarm}) { + showAlarmForm(context, alarm: alarm); + } +} + +class _EmptyState extends StatelessWidget { + final Color primaryColor; + + const _EmptyState({required this.primaryColor}); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.alarm_outlined, + color: primaryColor, + size: SizeUtils.getByScreen(small: 120, big: 140), + ), + SizedBox(height: SizeUtils.getByScreen(small: 20, big: 24)), + Text( + context.translate(I18n.noAlarms), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 16, big: 17), + color: Colors.grey, + ), + ), + ], + ), ); } } -class _AlarmsSection extends ConsumerWidget { +class _AlarmList extends ConsumerWidget { + final void Function(AlarmEntity alarm) onEdit; - const _AlarmsSection(); + const _AlarmList({required this.onEdit}); @override Widget build(BuildContext context, WidgetRef ref) { final alarms = ref.watch( - alarmViewModelProvider.select((s)=>s.alarms) + alarmViewModelProvider.select((s) => s.alarms), ); return SingleChildScrollView( - child: Column( - children: alarms.map((alarm) { - if (alarm == null) { - return const _NewAlarmButton(); - } - else{ - return _AlarmButton(alarm: alarm); - } - }).toList() + child: Padding( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), + big: EdgeInsets.symmetric(horizontal: 21, vertical: 8), + ), + child: Column( + children: alarms.map((alarm) { + return _AlarmCard( + alarm: alarm, + onEdit: () => onEdit(alarm), + ); + }).toList(), + ), ), ); } } -class _NewAlarmButton extends ConsumerWidget { - - const _NewAlarmButton(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - return TextButton( - onPressed: (){showDialog(context: context, builder: (context)=>Dialog( - child: NewAlarmDialog() - ));}, - child: Container( - padding: EdgeInsets.symmetric(horizontal: 18, vertical: 12), - decoration: BoxDecoration( - color: theme.getColorFor(ThemeCode.backgroundSecondary), - borderRadius: BorderRadius.all(Radius.circular(18)) - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(context.translate(I18n.addAlarm), - style: TextStyle( - fontWeight: FontWeight.w500, - color: theme.getColorFor(ThemeCode.textPrimary), - fontSize: 18 - ), - ), - DecoratedBox( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: theme.getColorFor(ThemeCode.legacyPrimary) - ), - child: Icon( - Icons.add, - color: theme.getColorFor(ThemeCode.textSecondary), - size: 58, - ), - ) - ], - ), - ), - ); - } - -} - -class _AlarmButton extends ConsumerWidget { - +class _AlarmCard extends ConsumerWidget { final AlarmEntity alarm; + final VoidCallback onEdit; - const _AlarmButton({ + const _AlarmCard({ required this.alarm, + required this.onEdit, }); @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); + final theme = ref.watch(themePortProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + final hh = alarm.time.hour.toString().padLeft(2, '0'); + final mm = alarm.time.minute.toString().padLeft(2, '0'); - return TextButton( - onPressed: (){showDialog(context: context, builder: (context)=>Dialog( - child: NewAlarmDialog() - ));}, + String typeLabel; + String? daysLabel; + switch (alarm.dateOption) { + case AlarmDateOption.once: + typeLabel = context.translate(I18n.once); + case AlarmDateOption.daily: + typeLabel = context.translate(I18n.daily); + daysLabel = context.translate(I18n.daily); + case AlarmDateOption.custom: + typeLabel = context.translate(I18n.selectDay); + final active = []; + for (final entry in weekDayI18nKeys.entries) { + final dayIndex = entry.key - 1; + if (alarm.days[dayIndex]) { + active.add(weekDayShortLabel(context, entry.value)); + } + } + daysLabel = active.join(' '); + } + + return Padding( + padding: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 12, big: 10), + ), child: Container( - padding: EdgeInsets.symmetric(), + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + vertical: SizeUtils.getByScreen(small: 14, big: 12), + ), decoration: BoxDecoration( color: theme.getColorFor(ThemeCode.backgroundSecondary), - borderRadius: BorderRadius.all(Radius.circular(18)) + borderRadius: BorderRadius.all(Radius.circular(16)), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '$hh:$mm', + style: TextStyle( + fontWeight: FontWeight.bold, + color: theme.getColorFor(ThemeCode.textPrimary), + fontSize: SizeUtils.getByScreen(small: 24, big: 26), + ), + ), + Text( + typeLabel, + style: TextStyle( + color: primaryColor, + fontSize: SizeUtils.getByScreen(small: 14, big: 15), + fontWeight: FontWeight.w500, + ), + ), + ], + ), + SizedBox(height: 4), + Text( + alarm.message, + style: TextStyle( + color: theme.getColorFor(ThemeCode.textPrimary).withAlpha(178), + fontSize: SizeUtils.getByScreen(small: 14, big: 15), + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + if (daysLabel != null) ...[ + SizedBox(height: 2), + Text( + daysLabel, + style: TextStyle( + color: theme.getColorFor(ThemeCode.textPrimary).withAlpha(128), + fontSize: SizeUtils.getByScreen(small: 12, big: 13), + ), + ), + ], + SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + _ActionButton( + icon: Icons.edit_outlined, + color: primaryColor, + onPressed: onEdit, + ), + SizedBox(width: SizeUtils.getByScreen(small: 8, big: 10)), + _ActionButton( + icon: Icons.delete_outline, + color: Colors.red, + onPressed: () => _confirmDelete(context, ref), + ), + ], + ), ], ), ), ); } -} \ No newline at end of file + void _confirmDelete(BuildContext context, WidgetRef ref) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(context.translate(I18n.deleteAlarm)), + content: Text(context.translate(I18n.deleteAlarmConfirm)), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(context.translate(I18n.cancel)), + ), + TextButton( + onPressed: () { + ref.read(alarmViewModelProvider.notifier).deleteAlarm(alarm.id); + Navigator.pop(context); + }, + child: Text( + context.translate(I18n.delete), + style: TextStyle(color: Colors.red), + ), + ), + ], + ), + ); + } +} + +class _ActionButton extends StatelessWidget { + final IconData icon; + final Color color; + final VoidCallback onPressed; + + const _ActionButton({ + required this.icon, + required this.color, + required this.onPressed, + }); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onPressed, + borderRadius: BorderRadius.circular(8), + child: Padding( + padding: EdgeInsets.all(SizeUtils.getByScreen(small: 6, big: 8)), + child: Icon( + icon, + color: color, + size: SizeUtils.getByScreen(small: 22, big: 24), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/providers/get_alarms_use_case_provider.dart b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/providers/get_alarms_use_case_provider.dart deleted file mode 100644 index 137266e0..00000000 --- a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/providers/get_alarms_use_case_provider.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:settings/src/core/providers/settings_repository_provider.dart'; -import 'package:settings/src/features/alarm/domain/get_alarms_use_case.dart'; -import 'package:settings/src/features/alarm/domain/get_alarms_use_case_impl.dart'; - -final getAlarmsUseCaseProvider = Provider.autoDispose((ref) { - final settingsRepository = ref.read(settingsRepositoryProvider); - return GetAlarmsUseCaseImpl(settingsRepository); -}); diff --git a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_model.dart b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_model.dart index 084ce46a..1c5f2889 100644 --- a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_model.dart +++ b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_model.dart @@ -1,73 +1,134 @@ -import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:legacy_shared/legacy_shared.dart'; -import 'package:settings/src/features/alarm/domain/get_alarms_use_case.dart'; -import 'package:settings/src/features/alarm/presentation/providers/get_alarms_use_case_provider.dart'; +import 'package:settings/src/core/data/models/create_alarm_request_model.dart'; +import 'package:settings/src/core/data/models/update_alarm_request_model.dart'; +import 'package:settings/src/core/domain/repositories/alarm_repository.dart'; +import 'package:settings/src/core/providers/alarm_repository_provider.dart'; +import 'package:settings/src/features/alarm/domain/entities/alarm_entity.dart'; import 'package:settings/src/features/alarm/presentation/state/alarm_view_state.dart'; - -import '../../domain/entities/alarm_entity.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:uuid/uuid.dart'; final alarmViewModelProvider = -NotifierProvider.autoDispose( + NotifierProvider.autoDispose( AlarmViewModel.new, ); class AlarmViewModel extends Notifier { - late final GetAlarmsUseCase _getAlarmsUseCase; - - // late final UserEntity loggedUser; + late final AlarmRepository _repository; @override AlarmViewState build() { - _getAlarmsUseCase = ref.read(getAlarmsUseCaseProvider); - - Future.microtask(() => load()); - + _repository = ref.read(alarmRepositoryProvider); + Future.microtask(_load); return const AlarmViewState(); } - Future load() async { - final device = ref.read(selectedDeviceProvider); + Future _load() async { + try { + final device = ref.read(selectedDeviceProvider); + if (device == null) return; - // final alarms = await _getAlarmsUseCase.getAlarms(deviceId: device.identificator); - // setAlarms(alarms); + final alarms = await _repository.getAlarms(deviceId: device.id); + state = state.copyWith(alarms: alarms, isLoading: false); + } catch (e) { + state = state.copyWith( + isLoading: false, + errorMessage: formatErrorMessage(e), + ); + } } - Future setAlarms(List alarms) async { - state = state.copyWith( - alarms: alarms, - isLoading: false, - ); + Future createAlarm(AlarmEntity alarm) async { + state = state.copyWith(isSaving: true, errorMessage: ''); + + try { + final device = ref.read(selectedDeviceProvider); + if (device == null) return; + + final id = const Uuid().v4(); + final request = CreateAlarmRequestModel( + id: id, + deviceId: device.id, + time: alarm.encodedTime, + message: alarm.message, + order: state.alarms.length + 1, + ); + + await _repository.createAlarm(request: request); + + final updatedAlarm = alarm.copyWith( + id: id, + deviceId: device.id, + order: state.alarms.length + 1, + ); + + state = state.copyWith( + alarms: [...state.alarms, updatedAlarm], + isSaving: false, + successMessage: I18n.alarmCreated, + ); + } catch (e) { + state = state.copyWith( + isSaving: false, + errorMessage: formatErrorMessage(e), + ); + } } - void setAlarmTime(TimeOfDay? value) { - if (value == null) return; - if (state.alarmTime == value) return; + Future updateAlarm(AlarmEntity alarm) async { + state = state.copyWith(isSaving: true, errorMessage: ''); - state = state.copyWith( - alarmTime: value, - ); + try { + final request = UpdateAlarmRequestModel( + deviceId: alarm.deviceId, + time: alarm.encodedTime, + message: alarm.message, + order: alarm.order, + ); + + await _repository.updateAlarm(alarmId: alarm.id, request: request); + + final updatedAlarms = state.alarms + .map((a) => a.id == alarm.id ? alarm : a) + .toList(); + + state = state.copyWith( + alarms: updatedAlarms, + isSaving: false, + successMessage: I18n.alarmUpdated, + ); + } catch (e) { + state = state.copyWith( + isSaving: false, + errorMessage: formatErrorMessage(e), + ); + } } - void setDateOption(String value) { - if (state.dateOption == value) return; + Future deleteAlarm(String alarmId) async { + state = state.copyWith(isSaving: true, errorMessage: ''); - state = state.copyWith( - dateOption: value, - ); + try { + await _repository.deleteAlarm(alarmId: alarmId); + + final updatedAlarms = + state.alarms.where((a) => a.id != alarmId).toList(); + + state = state.copyWith( + alarms: updatedAlarms, + isSaving: false, + successMessage: I18n.alarmDeleted, + ); + } catch (e) { + state = state.copyWith( + isSaving: false, + errorMessage: formatErrorMessage(e), + ); + } } - void toggleAlarmDay(int index) { - List alarmDays = state.alarmDays.toList(); - - alarmDays[index] = !alarmDays[index]; - - state = state.copyWith( - alarmDays: alarmDays, - ); - } - - Future setAlarm() async { - + void clearSuccess() { + state = state.copyWith(successMessage: ''); } } diff --git a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_state.dart b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_state.dart index e940455a..f6554a20 100644 --- a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_state.dart +++ b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_state.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:settings/src/features/alarm/domain/entities/alarm_entity.dart'; @@ -7,11 +6,10 @@ part 'alarm_view_state.freezed.dart'; @freezed abstract class AlarmViewState with _$AlarmViewState { const factory AlarmViewState({ - @Default([null, null, null]) List alarms, - @Default(TimeOfDay(hour: 0, minute: 0)) TimeOfDay alarmTime, - @Default('ONCE') String dateOption, - @Default([false, false, false, false, false, false, false]) List alarmDays, + @Default([]) List alarms, @Default(true) bool isLoading, + @Default(false) bool isSaving, + @Default('') String successMessage, @Default('') String errorMessage, }) = _AlarmViewState; } diff --git a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_state.freezed.dart b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_state.freezed.dart index 210b92c5..ed4ef10e 100644 --- a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_state.freezed.dart +++ b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/state/alarm_view_state.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$AlarmViewState { - List get alarms; TimeOfDay get alarmTime; String get dateOption; List get alarmDays; bool get isLoading; String get errorMessage; + List get alarms; bool get isLoading; bool get isSaving; String get successMessage; String get errorMessage; /// Create a copy of AlarmViewState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $AlarmViewStateCopyWith get copyWith => _$AlarmViewStateCopyWith @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is AlarmViewState&&const DeepCollectionEquality().equals(other.alarms, alarms)&&(identical(other.alarmTime, alarmTime) || other.alarmTime == alarmTime)&&(identical(other.dateOption, dateOption) || other.dateOption == dateOption)&&const DeepCollectionEquality().equals(other.alarmDays, alarmDays)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is AlarmViewState&&const DeepCollectionEquality().equals(other.alarms, alarms)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.successMessage, successMessage) || other.successMessage == successMessage)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(alarms),alarmTime,dateOption,const DeepCollectionEquality().hash(alarmDays),isLoading,errorMessage); +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(alarms),isLoading,isSaving,successMessage,errorMessage); @override String toString() { - return 'AlarmViewState(alarms: $alarms, alarmTime: $alarmTime, dateOption: $dateOption, alarmDays: $alarmDays, isLoading: $isLoading, errorMessage: $errorMessage)'; + return 'AlarmViewState(alarms: $alarms, isLoading: $isLoading, isSaving: $isSaving, successMessage: $successMessage, errorMessage: $errorMessage)'; } @@ -45,7 +45,7 @@ abstract mixin class $AlarmViewStateCopyWith<$Res> { factory $AlarmViewStateCopyWith(AlarmViewState value, $Res Function(AlarmViewState) _then) = _$AlarmViewStateCopyWithImpl; @useResult $Res call({ - List alarms, TimeOfDay alarmTime, String dateOption, List alarmDays, bool isLoading, String errorMessage + List alarms, bool isLoading, bool isSaving, String successMessage, String errorMessage }); @@ -62,14 +62,13 @@ class _$AlarmViewStateCopyWithImpl<$Res> /// Create a copy of AlarmViewState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? alarms = null,Object? alarmTime = null,Object? dateOption = null,Object? alarmDays = null,Object? isLoading = null,Object? errorMessage = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? alarms = null,Object? isLoading = null,Object? isSaving = null,Object? successMessage = null,Object? errorMessage = null,}) { return _then(_self.copyWith( alarms: null == alarms ? _self.alarms : alarms // ignore: cast_nullable_to_non_nullable -as List,alarmTime: null == alarmTime ? _self.alarmTime : alarmTime // ignore: cast_nullable_to_non_nullable -as TimeOfDay,dateOption: null == dateOption ? _self.dateOption : dateOption // ignore: cast_nullable_to_non_nullable -as String,alarmDays: null == alarmDays ? _self.alarmDays : alarmDays // ignore: cast_nullable_to_non_nullable -as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable -as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable +as bool,successMessage: null == successMessage ? _self.successMessage : successMessage // ignore: cast_nullable_to_non_nullable +as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String, )); } @@ -155,10 +154,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( List alarms, TimeOfDay alarmTime, String dateOption, List alarmDays, bool isLoading, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( List alarms, bool isLoading, bool isSaving, String successMessage, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _AlarmViewState() when $default != null: -return $default(_that.alarms,_that.alarmTime,_that.dateOption,_that.alarmDays,_that.isLoading,_that.errorMessage);case _: +return $default(_that.alarms,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: return orElse(); } @@ -176,10 +175,10 @@ return $default(_that.alarms,_that.alarmTime,_that.dateOption,_that.alarmDays,_t /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( List alarms, TimeOfDay alarmTime, String dateOption, List alarmDays, bool isLoading, String errorMessage) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( List alarms, bool isLoading, bool isSaving, String successMessage, String errorMessage) $default,) {final _that = this; switch (_that) { case _AlarmViewState(): -return $default(_that.alarms,_that.alarmTime,_that.dateOption,_that.alarmDays,_that.isLoading,_that.errorMessage);case _: +return $default(_that.alarms,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: throw StateError('Unexpected subclass'); } @@ -196,10 +195,10 @@ return $default(_that.alarms,_that.alarmTime,_that.dateOption,_that.alarmDays,_t /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( List alarms, TimeOfDay alarmTime, String dateOption, List alarmDays, bool isLoading, String errorMessage)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List alarms, bool isLoading, bool isSaving, String successMessage, String errorMessage)? $default,) {final _that = this; switch (_that) { case _AlarmViewState() when $default != null: -return $default(_that.alarms,_that.alarmTime,_that.dateOption,_that.alarmDays,_that.isLoading,_that.errorMessage);case _: +return $default(_that.alarms,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: return null; } @@ -211,26 +210,19 @@ return $default(_that.alarms,_that.alarmTime,_that.dateOption,_that.alarmDays,_t class _AlarmViewState implements AlarmViewState { - const _AlarmViewState({final List alarms = const [null, null, null], this.alarmTime = const TimeOfDay(hour: 0, minute: 0), this.dateOption = 'ONCE', final List alarmDays = const [false, false, false, false, false, false, false], this.isLoading = true, this.errorMessage = ''}): _alarms = alarms,_alarmDays = alarmDays; + const _AlarmViewState({final List alarms = const [], this.isLoading = true, this.isSaving = false, this.successMessage = '', this.errorMessage = ''}): _alarms = alarms; - final List _alarms; -@override@JsonKey() List get alarms { + final List _alarms; +@override@JsonKey() List get alarms { if (_alarms is EqualUnmodifiableListView) return _alarms; // ignore: implicit_dynamic_type return EqualUnmodifiableListView(_alarms); } -@override@JsonKey() final TimeOfDay alarmTime; -@override@JsonKey() final String dateOption; - final List _alarmDays; -@override@JsonKey() List get alarmDays { - if (_alarmDays is EqualUnmodifiableListView) return _alarmDays; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_alarmDays); -} - @override@JsonKey() final bool isLoading; +@override@JsonKey() final bool isSaving; +@override@JsonKey() final String successMessage; @override@JsonKey() final String errorMessage; /// Create a copy of AlarmViewState @@ -243,16 +235,16 @@ _$AlarmViewStateCopyWith<_AlarmViewState> get copyWith => __$AlarmViewStateCopyW @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _AlarmViewState&&const DeepCollectionEquality().equals(other._alarms, _alarms)&&(identical(other.alarmTime, alarmTime) || other.alarmTime == alarmTime)&&(identical(other.dateOption, dateOption) || other.dateOption == dateOption)&&const DeepCollectionEquality().equals(other._alarmDays, _alarmDays)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AlarmViewState&&const DeepCollectionEquality().equals(other._alarms, _alarms)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.successMessage, successMessage) || other.successMessage == successMessage)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_alarms),alarmTime,dateOption,const DeepCollectionEquality().hash(_alarmDays),isLoading,errorMessage); +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_alarms),isLoading,isSaving,successMessage,errorMessage); @override String toString() { - return 'AlarmViewState(alarms: $alarms, alarmTime: $alarmTime, dateOption: $dateOption, alarmDays: $alarmDays, isLoading: $isLoading, errorMessage: $errorMessage)'; + return 'AlarmViewState(alarms: $alarms, isLoading: $isLoading, isSaving: $isSaving, successMessage: $successMessage, errorMessage: $errorMessage)'; } @@ -263,7 +255,7 @@ abstract mixin class _$AlarmViewStateCopyWith<$Res> implements $AlarmViewStateCo factory _$AlarmViewStateCopyWith(_AlarmViewState value, $Res Function(_AlarmViewState) _then) = __$AlarmViewStateCopyWithImpl; @override @useResult $Res call({ - List alarms, TimeOfDay alarmTime, String dateOption, List alarmDays, bool isLoading, String errorMessage + List alarms, bool isLoading, bool isSaving, String successMessage, String errorMessage }); @@ -280,14 +272,13 @@ class __$AlarmViewStateCopyWithImpl<$Res> /// Create a copy of AlarmViewState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? alarms = null,Object? alarmTime = null,Object? dateOption = null,Object? alarmDays = null,Object? isLoading = null,Object? errorMessage = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? alarms = null,Object? isLoading = null,Object? isSaving = null,Object? successMessage = null,Object? errorMessage = null,}) { return _then(_AlarmViewState( alarms: null == alarms ? _self._alarms : alarms // ignore: cast_nullable_to_non_nullable -as List,alarmTime: null == alarmTime ? _self.alarmTime : alarmTime // ignore: cast_nullable_to_non_nullable -as TimeOfDay,dateOption: null == dateOption ? _self.dateOption : dateOption // ignore: cast_nullable_to_non_nullable -as String,alarmDays: null == alarmDays ? _self._alarmDays : alarmDays // ignore: cast_nullable_to_non_nullable -as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable -as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable +as bool,successMessage: null == successMessage ? _self.successMessage : successMessage // ignore: cast_nullable_to_non_nullable +as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String, )); } diff --git a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/widgets/alarm_form_screen.dart b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/widgets/alarm_form_screen.dart new file mode 100644 index 00000000..9082d2d3 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/widgets/alarm_form_screen.dart @@ -0,0 +1,312 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:settings/src/features/alarm/domain/entities/alarm_entity.dart'; +import 'package:settings/src/features/alarm/presentation/state/alarm_view_model.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +void showAlarmForm(BuildContext context, {AlarmEntity? alarm}) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (_) => _AlarmFormSheet(alarm: alarm), + ); +} + +class _AlarmFormSheet extends ConsumerStatefulWidget { + final AlarmEntity? alarm; + + const _AlarmFormSheet({this.alarm}); + + @override + ConsumerState<_AlarmFormSheet> createState() => _AlarmFormSheetState(); +} + +class _AlarmFormSheetState extends ConsumerState<_AlarmFormSheet> { + late Duration _duration; + late AlarmDateOption _dateOption; + late List _days; + late TextEditingController _messageController; + + bool get _isEditing => widget.alarm != null; + + @override + void initState() { + super.initState(); + final time = widget.alarm?.time ?? const TimeOfDay(hour: 8, minute: 0); + _duration = Duration(hours: time.hour, minutes: time.minute); + _dateOption = widget.alarm?.dateOption ?? AlarmDateOption.once; + _days = widget.alarm?.days.toList() ?? List.filled(7, false); + _messageController = TextEditingController( + text: widget.alarm?.message ?? '', + ); + } + + @override + void dispose() { + _messageController.dispose(); + super.dispose(); + } + + bool get _canSave { + if (_messageController.text.trim().isEmpty) return false; + if (_dateOption == AlarmDateOption.custom && !_days.contains(true)) { + return false; + } + return true; + } + + void _save() { + if (!_canSave) return; + + final vm = ref.read(alarmViewModelProvider.notifier); + final time = TimeOfDay( + hour: _duration.inHours % 24, + minute: _duration.inMinutes % 60, + ); + + final entity = AlarmEntity( + id: widget.alarm?.id ?? '', + deviceId: widget.alarm?.deviceId ?? '', + time: time, + message: _messageController.text.trim(), + order: widget.alarm?.order ?? 0, + dateOption: _dateOption, + days: _days, + ); + + if (_isEditing) { + vm.updateAlarm(entity); + } else { + vm.createAlarm(entity); + } + + Navigator.pop(context); + } + + @override + Widget build(BuildContext context) { + final theme = ref.watch(themePortProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + final bottomInset = MediaQuery.of(context).viewInsets.bottom; + + return Padding( + padding: EdgeInsets.only(bottom: bottomInset), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + child: SafeArea( + top: false, + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 22, big: 24), + vertical: SizeUtils.getByScreen(small: 16, big: 18), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Handle bar + Center( + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey.shade300, + borderRadius: BorderRadius.circular(2), + ), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 14)), + + // Header + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + _isEditing + ? context.translate(I18n.editAlarm) + : context.translate(I18n.addAlarm), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 21), + fontWeight: FontWeight.w600, + color: primaryColor, + ), + ), + TextButton( + onPressed: _canSave ? _save : null, + child: Text( + context.translate(I18n.save), + style: TextStyle( + color: _canSave ? primaryColor : Colors.grey, + fontWeight: FontWeight.w600, + fontSize: + SizeUtils.getByScreen(small: 16, big: 17), + ), + ), + ), + ], + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 18)), + + // Time picker + Container( + height: SizeUtils.getByScreen(small: 160, big: 180), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(16)), + color: Colors.grey.shade50, + ), + child: CupertinoTimerPicker( + mode: CupertinoTimerPickerMode.hm, + initialTimerDuration: _duration, + onTimerDurationChanged: (d) { + setState(() => _duration = d); + }, + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 20, big: 22)), + + // Message + Text( + context.translate(I18n.alarmMessage), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 16), + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 8), + TextField( + controller: _messageController, + onChanged: (_) => setState(() {}), + decoration: InputDecoration( + hintText: context.translate(I18n.alarmMessageHint), + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: Colors.grey.shade300), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: Colors.grey.shade300), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: primaryColor, width: 2), + ), + contentPadding: EdgeInsets.symmetric( + horizontal: 14, + vertical: 14, + ), + ), + maxLines: 1, + ), + SizedBox(height: SizeUtils.getByScreen(small: 20, big: 22)), + + // Repetition + Text( + context.translate(I18n.selectDay), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 16), + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 8), + _RadioOption( + label: context.translate(I18n.once), + isSelected: _dateOption == AlarmDateOption.once, + primaryColor: primaryColor, + onTap: () => + setState(() => _dateOption = AlarmDateOption.once), + ), + _RadioOption( + label: context.translate(I18n.daily), + isSelected: _dateOption == AlarmDateOption.daily, + primaryColor: primaryColor, + onTap: () => + setState(() => _dateOption = AlarmDateOption.daily), + ), + _RadioOption( + label: context.translate(I18n.selectDay), + isSelected: _dateOption == AlarmDateOption.custom, + primaryColor: primaryColor, + onTap: () => + setState(() => _dateOption = AlarmDateOption.custom), + ), + + // Day chips + if (_dateOption == AlarmDateOption.custom) ...[ + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 14)), + WeekDayChips.multi( + selectedDays: _days, + onToggle: (index) { + setState(() { + _days = _days.toList(); + _days[index] = !_days[index]; + }); + }, + theme: theme, + ), + ], + + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 18)), + ], + ), + ), + ), + ), + ), + ); + } +} + +class _RadioOption extends StatelessWidget { + final String label; + final bool isSelected; + final Color primaryColor; + final VoidCallback onTap; + + const _RadioOption({ + required this.label, + required this.isSelected, + required this.primaryColor, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(8), + child: Padding( + padding: EdgeInsets.symmetric( + vertical: SizeUtils.getByScreen(small: 8, big: 10), + ), + child: Row( + children: [ + Icon( + isSelected ? Icons.radio_button_checked : Icons.radio_button_off, + color: isSelected ? primaryColor : Colors.grey, + size: SizeUtils.getByScreen(small: 22, big: 24), + ), + SizedBox(width: 12), + Text( + label, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 16), + color: isSelected ? primaryColor : null, + fontWeight: isSelected ? FontWeight.w500 : FontWeight.normal, + ), + ), + ], + ), + ), + ); + } +} + diff --git a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/widgets/new_alarm_dialog.dart b/modules/legacy/modules/settings/lib/src/features/alarm/presentation/widgets/new_alarm_dialog.dart deleted file mode 100644 index 8e35d41c..00000000 --- a/modules/legacy/modules/settings/lib/src/features/alarm/presentation/widgets/new_alarm_dialog.dart +++ /dev/null @@ -1,245 +0,0 @@ -import 'package:design_system/design_system.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:settings/src/features/alarm/presentation/state/alarm_view_model.dart'; -import 'package:sf_localizations/sf_localizations.dart'; - -class NewAlarmDialog extends ConsumerWidget { - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - return Container( - decoration: BoxDecoration( - color: theme.getColorFor(ThemeCode.backgroundSecondary), - borderRadius: BorderRadius.all(Radius.circular(8)), - ), - height: 290, - padding: EdgeInsets.symmetric(horizontal: 12, vertical: 20), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _Header(theme: theme), - const _TimeSection(), - const _DaysSection(), - const _SaveSection(), - ], - ), - ); - } -} - -class _Header extends StatelessWidget { - - final ThemePort theme; - - const _Header({ - required this.theme, - }); - - @override - Widget build(BuildContext context) { - return Stack( - children: [ - Center(child: Text(context.translate(I18n.alarmSettings).toUpperCase(), - style: TextStyle( - color: theme.getColorFor(ThemeCode.legacyPrimary) - ), - )), - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: (){Navigator.pop(context);}, - padding: EdgeInsets.zero, - icon: Icon( - Icons.close, - color: theme.getColorFor(ThemeCode.legacyPrimary), - size: 18, - ) - ), - ) - ], - ); - } -} - -class _TimeSection extends ConsumerWidget { - - const _TimeSection(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - final vm = ref.read(alarmViewModelProvider.notifier); - final alarmTime = ref.watch( - alarmViewModelProvider.select((s) => s.alarmTime) - ); - final dateOption = ref.watch( - alarmViewModelProvider.select((s) => s.dateOption) - ); - - Map dateOptions = { - 'ONCE': context.translate(I18n.once), - 'DAILY': context.translate(I18n.daily), - 'SELECT': context.translate(I18n.selectDay), - }; - - return Column( - children: [ - Text(context.translate(I18n.setDateTime), - style: TextStyle( - color: theme.getColorFor(ThemeCode.legacyPrimary) - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TextButton( - onPressed: () async { - final time = await showTimePicker( - context: context, - initialTime: const TimeOfDay(hour: 00, minute: 00), - builder: (BuildContext context, Widget? child) { - return MediaQuery( - data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true), - child: child!, - ); - }, - ); - - vm.setAlarmTime(time); - }, - child: Container( - decoration: BoxDecoration( - border: Border.fromBorderSide(BorderSide( - color: theme.getColorFor(ThemeCode.legacyPrimary) - )), - borderRadius: BorderRadius.all(Radius.circular(14)) - ), - width: 128, - height: 50, - padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4), - child: Center( - child: Text('${alarmTime.hour.toString().padLeft(2, '0')}:' - '${alarmTime.minute.toString().padLeft(2, '0')}', - style: TextStyle( - color: theme.getColorFor(ThemeCode.legacyPrimary) - ), - ), - ), - ), - ), - Expanded(child: CustomDropdown( - items: dateOptions.values - .map(Text.new) - .toList(growable: false), - values: dateOptions.keys.toList(growable: false), - value: dateOption, - onChanged: (value){ - vm.setDateOption(value); - }, - height: 50, - color: theme.getColorFor(ThemeCode.legacyPrimary), - )) - ], - ) - ], - ); - } -} - -class _DaysSection extends ConsumerWidget { - - const _DaysSection(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - - final theme = ref.read(themePortProvider); - - final vm = ref.read(alarmViewModelProvider.notifier); - final dateOption = ref.watch( - alarmViewModelProvider.select((s)=>s.dateOption) - ); - final alarmDays = ref.watch( - alarmViewModelProvider.select((s)=>s.alarmDays) - ); - - final days = [ - 'LUN', - 'MAR', - 'MIE', - 'JUE', - 'VIE', - 'SAB', - 'DOM', - ]; - - if (dateOption == 'SELECT') { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: List.generate(days.length, (int index){ - return TextButton( - onPressed: (){ - vm.toggleAlarmDay(index); - }, - style: ButtonStyle( - padding: WidgetStatePropertyAll(EdgeInsets.zero), - minimumSize: WidgetStatePropertyAll(Size.zero), - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - child: Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: alarmDays[index] - ? theme.getColorFor(ThemeCode.legacyPrimary) - : theme.getColorFor(ThemeCode.backgroundPrimary), - border: Border.fromBorderSide( - BorderSide(color: theme.getColorFor(ThemeCode.legacyPrimary)) - ), - ), - padding: EdgeInsets.all(8), - child: Text(days[index], - style: TextStyle( - color: alarmDays[index] - ? theme.getColorFor(ThemeCode.textSecondary) - : theme.getColorFor(ThemeCode.textPrimary), - fontSize: 12 - ), - ), - ) - ); - }) - ); - } - else { - return SizedBox.shrink(); - } - } - -} - -class _SaveSection extends ConsumerWidget { - - const _SaveSection(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - final vm = ref.read(alarmViewModelProvider.notifier); - - return PrimaryButton( - onPressed: (){ - vm.setAlarm(); - - Navigator.pop(context); - }, - text: context.translate(I18n.save), - color: theme.getColorFor(ThemeCode.legacyPrimary) - ); - } -} \ No newline at end of file diff --git a/modules/legacy/modules/settings/lib/src/features/app_store/app_store_builder.dart b/modules/legacy/modules/settings/lib/src/features/app_store/app_store_builder.dart new file mode 100644 index 00000000..e31a0f62 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/app_store/app_store_builder.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import 'presentation/app_store_screen.dart'; + +class AppStoreBuilder { + const AppStoreBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + return MaterialPage( + key: state.pageKey, + child: const AppStoreScreen(), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/app_store/presentation/app_store_screen.dart b/modules/legacy/modules/settings/lib/src/features/app_store/presentation/app_store_screen.dart new file mode 100644 index 00000000..8bf23e95 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/app_store/presentation/app_store_screen.dart @@ -0,0 +1,22 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class AppStoreScreen extends ConsumerWidget { + const AppStoreScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.appStore), + body: const Center( + child: Text('Coming soon'), + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/battery/battery_builder.dart b/modules/legacy/modules/settings/lib/src/features/battery/battery_builder.dart new file mode 100644 index 00000000..db739015 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/battery/battery_builder.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import 'presentation/battery_screen.dart'; + +class BatteryBuilder { + const BatteryBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + return MaterialPage( + key: state.pageKey, + child: const BatteryScreen(), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/battery/presentation/battery_screen.dart b/modules/legacy/modules/settings/lib/src/features/battery/presentation/battery_screen.dart new file mode 100644 index 00000000..eb4af320 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/battery/presentation/battery_screen.dart @@ -0,0 +1,22 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class BatteryScreen extends ConsumerWidget { + const BatteryScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.battery), + body: const Center( + child: Text('Coming soon'), + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/block_phone/block_phone_builder.dart b/modules/legacy/modules/settings/lib/src/features/block_phone/block_phone_builder.dart new file mode 100644 index 00000000..9bfc6a01 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/block_phone/block_phone_builder.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:go_router/go_router.dart'; +import 'package:navigation/navigation.dart'; +import 'package:settings/src/features/block_phone/presentation/block_phone_screen.dart'; + +class BlockPhoneBuilder { + const BlockPhoneBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = + GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: BlockPhoneScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/block_phone_screen.dart b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/block_phone_screen.dart new file mode 100644 index 00000000..757e7a18 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/block_phone_screen.dart @@ -0,0 +1,260 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:navigation/navigation.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import 'state/block_phone_view_model.dart'; +import '../../../core/presentation/widgets/contact_list_contact_card.dart'; +import 'widgets/add_contact_sheet.dart'; + +class BlockPhoneScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const BlockPhoneScreen({ + super.key, + required this.navigationContract, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final state = ref.watch(blockPhoneViewModelProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + + ref.listen( + blockPhoneViewModelProvider.select((s) => s.errorMessage), + (_, errorMessage) { + if (errorMessage.isNotEmpty) { + showTopSnackbar( + context, + message: errorMessage, + type: MessageType.error, + ); + } + }, + ); + + ref.listen( + blockPhoneViewModelProvider.select((s) => s.successMessage), + (_, successMessage) { + if (successMessage.isNotEmpty) { + showTopSnackbar( + context, + message: context.translate(successMessage), + type: MessageType.success, + ); + ref.read(blockPhoneViewModelProvider.notifier).clearSuccess(); + } + }, + ); + + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + surfaceTintColor: Colors.transparent, + elevation: 0, + centerTitle: true, + automaticallyImplyLeading: false, + leading: IconButton( + onPressed: () => navigationContract.goBack(), + icon: Icon( + Icons.adaptive.arrow_back, + color: primaryColor, + size: SizeUtils.getByScreen(small: 32, big: 28), + ), + ), + title: Text( + context.translate(I18n.blockPhone).toUpperCase(), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 19), + fontWeight: FontWeight.w500, + letterSpacing: 0, + color: primaryColor, + ), + ), + actions: [ + Padding( + padding: EdgeInsets.only( + right: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: DecoratedBox( + decoration: BoxDecoration( + color: primaryColor, + shape: BoxShape.circle, + ), + child: IconButton( + onPressed: () => showAddContactSheet(context), + icon: Icon( + Icons.add, + color: Colors.white, + size: SizeUtils.getByScreen(small: 24, big: 22), + ), + ), + ), + ), + ], + ), + body: SafeArea( + top: false, + child: state.isLoading + ? const Center(child: CircularProgressIndicator()) + : state.contacts.isEmpty + ? _EmptyState(primaryColor: primaryColor) + : _ContactList(), + ), + ); + } +} + +class _EmptyState extends StatelessWidget { + final Color primaryColor; + + const _EmptyState({required this.primaryColor}); + + @override + Widget build(BuildContext context) { + return Center( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 32, big: 30), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.phone_locked_outlined, + color: primaryColor, + size: SizeUtils.getByScreen(small: 120, big: 140), + ), + SizedBox(height: SizeUtils.getByScreen(small: 20, big: 24)), + Text( + context.translate(I18n.noBlockedNumbers), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 16, big: 17), + fontWeight: FontWeight.w500, + color: Colors.grey, + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 10)), + Text( + context.translate(I18n.noBlockedNumbersDescription), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 15), + color: Colors.grey, + ), + ), + ], + ), + ), + ); + } +} + +class _ContactList extends ConsumerWidget { + const _ContactList(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final contacts = ref.watch( + blockPhoneViewModelProvider.select((s) => s.contacts), + ); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + + return SingleChildScrollView( + child: Padding( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), + big: EdgeInsets.symmetric(horizontal: 21, vertical: 8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 12, big: 10), + ), + child: Text( + context.translate(I18n.whitelistDescription), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 15), + color: + theme.getColorFor(ThemeCode.textPrimary).withAlpha(178), + ), + ), + ), + ...List.generate(contacts.length, (index) { + final contact = contacts[index]; + return ContactListContactCard( + contact: contact, + onDelete: () => + _confirmDelete(context, ref, index, contact.name), + theme: theme, + ); + }), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), + Text( + context.translate( + I18n.allowedNumbersCount, + args: {'count': contacts.length.toString()}, + ), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 14), + color: primaryColor, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ); + } + + void _confirmDelete( + BuildContext context, + WidgetRef ref, + int index, + String name, + ) { + final theme = ref.read(themePortProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(context.translate(I18n.removeAllowedNumber)), + content: Text( + context.translate( + I18n.removeAllowedNumberConfirm, + args: {'name': name}, + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text( + context.translate(I18n.cancel), + style: TextStyle(color: primaryColor), + ), + ), + TextButton( + onPressed: () { + ref + .read(blockPhoneViewModelProvider.notifier) + .removeContact(index); + Navigator.pop(context); + }, + child: Text( + context.translate(I18n.delete), + style: TextStyle(color: Colors.red), + ), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/state/block_phone_view_model.dart b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/state/block_phone_view_model.dart new file mode 100644 index 00000000..0bc71456 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/state/block_phone_view_model.dart @@ -0,0 +1,98 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:settings/src/core/domain/entities/contact_list_contact_entity.dart'; +import 'package:settings/src/core/domain/repositories/block_phone_repository.dart'; +import 'package:settings/src/core/providers/block_phone_repository_provider.dart'; +import 'package:settings/src/features/block_phone/presentation/state/block_phone_view_state.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +final blockPhoneViewModelProvider = + NotifierProvider.autoDispose( + BlockPhoneViewModel.new, +); + +class BlockPhoneViewModel extends Notifier { + late final BlockPhoneRepository _repository; + + @override + BlockPhoneViewState build() { + _repository = ref.read(blockPhoneRepositoryProvider); + Future.microtask(_load); + return const BlockPhoneViewState(); + } + + Future _load() async { + try { + final device = ref.read(selectedDeviceProvider); + if (device == null) return; + + final contacts = await _repository.getWhitelist(deviceId: device.id); + state = state.copyWith(contacts: contacts, isLoading: false); + } catch (e) { + state = state.copyWith( + isLoading: false, + errorMessage: formatErrorMessage(e), + ); + } + } + + Future addContact(ContactListContactEntity contact) async { + state = state.copyWith(isSaving: true, errorMessage: ''); + + try { + final device = ref.read(selectedDeviceProvider); + if (device == null) return; + + final updatedContacts = [...state.contacts, contact]; + + await _repository.upsertWhitelist( + userId: device.userId ?? '', + deviceId: device.id, + contacts: updatedContacts, + ); + + state = state.copyWith( + contacts: updatedContacts, + isSaving: false, + successMessage: I18n.numberAdded, + ); + } catch (e) { + state = state.copyWith( + isSaving: false, + errorMessage: formatErrorMessage(e), + ); + } + } + + Future removeContact(int index) async { + state = state.copyWith(isSaving: true, errorMessage: ''); + + try { + final device = ref.read(selectedDeviceProvider); + if (device == null) return; + + final updatedContacts = [...state.contacts]..removeAt(index); + + await _repository.upsertWhitelist( + userId: device.userId ?? '', + deviceId: device.id, + contacts: updatedContacts, + ); + + state = state.copyWith( + contacts: updatedContacts, + isSaving: false, + successMessage: I18n.numberRemoved, + ); + } catch (e) { + state = state.copyWith( + isSaving: false, + errorMessage: formatErrorMessage(e), + ); + } + } + + void clearSuccess() { + state = state.copyWith(successMessage: ''); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/state/block_phone_view_state.dart b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/state/block_phone_view_state.dart new file mode 100644 index 00000000..18ef077a --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/state/block_phone_view_state.dart @@ -0,0 +1,15 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:settings/src/core/domain/entities/contact_list_contact_entity.dart'; + +part 'block_phone_view_state.freezed.dart'; + +@freezed +abstract class BlockPhoneViewState with _$BlockPhoneViewState { + const factory BlockPhoneViewState({ + @Default([]) List contacts, + @Default(true) bool isLoading, + @Default(false) bool isSaving, + @Default('') String successMessage, + @Default('') String errorMessage, + }) = _BlockPhoneViewState; +} diff --git a/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/state/block_phone_view_state.freezed.dart b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/state/block_phone_view_state.freezed.dart new file mode 100644 index 00000000..a11757f4 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/state/block_phone_view_state.freezed.dart @@ -0,0 +1,289 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'block_phone_view_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$BlockPhoneViewState { + + List get contacts; bool get isLoading; bool get isSaving; String get successMessage; String get errorMessage; +/// Create a copy of BlockPhoneViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$BlockPhoneViewStateCopyWith get copyWith => _$BlockPhoneViewStateCopyWithImpl(this as BlockPhoneViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is BlockPhoneViewState&&const DeepCollectionEquality().equals(other.contacts, contacts)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.successMessage, successMessage) || other.successMessage == successMessage)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(contacts),isLoading,isSaving,successMessage,errorMessage); + +@override +String toString() { + return 'BlockPhoneViewState(contacts: $contacts, isLoading: $isLoading, isSaving: $isSaving, successMessage: $successMessage, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class $BlockPhoneViewStateCopyWith<$Res> { + factory $BlockPhoneViewStateCopyWith(BlockPhoneViewState value, $Res Function(BlockPhoneViewState) _then) = _$BlockPhoneViewStateCopyWithImpl; +@useResult +$Res call({ + List contacts, bool isLoading, bool isSaving, String successMessage, String errorMessage +}); + + + + +} +/// @nodoc +class _$BlockPhoneViewStateCopyWithImpl<$Res> + implements $BlockPhoneViewStateCopyWith<$Res> { + _$BlockPhoneViewStateCopyWithImpl(this._self, this._then); + + final BlockPhoneViewState _self; + final $Res Function(BlockPhoneViewState) _then; + +/// Create a copy of BlockPhoneViewState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? contacts = null,Object? isLoading = null,Object? isSaving = null,Object? successMessage = null,Object? errorMessage = null,}) { + return _then(_self.copyWith( +contacts: null == contacts ? _self.contacts : contacts // ignore: cast_nullable_to_non_nullable +as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable +as bool,successMessage: null == successMessage ? _self.successMessage : successMessage // ignore: cast_nullable_to_non_nullable +as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [BlockPhoneViewState]. +extension BlockPhoneViewStatePatterns on BlockPhoneViewState { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _BlockPhoneViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _BlockPhoneViewState() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _BlockPhoneViewState value) $default,){ +final _that = this; +switch (_that) { +case _BlockPhoneViewState(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _BlockPhoneViewState value)? $default,){ +final _that = this; +switch (_that) { +case _BlockPhoneViewState() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( List contacts, bool isLoading, bool isSaving, String successMessage, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _BlockPhoneViewState() when $default != null: +return $default(_that.contacts,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( List contacts, bool isLoading, bool isSaving, String successMessage, String errorMessage) $default,) {final _that = this; +switch (_that) { +case _BlockPhoneViewState(): +return $default(_that.contacts,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List contacts, bool isLoading, bool isSaving, String successMessage, String errorMessage)? $default,) {final _that = this; +switch (_that) { +case _BlockPhoneViewState() when $default != null: +return $default(_that.contacts,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _BlockPhoneViewState implements BlockPhoneViewState { + const _BlockPhoneViewState({final List contacts = const [], this.isLoading = true, this.isSaving = false, this.successMessage = '', this.errorMessage = ''}): _contacts = contacts; + + + final List _contacts; +@override@JsonKey() List get contacts { + if (_contacts is EqualUnmodifiableListView) return _contacts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_contacts); +} + +@override@JsonKey() final bool isLoading; +@override@JsonKey() final bool isSaving; +@override@JsonKey() final String successMessage; +@override@JsonKey() final String errorMessage; + +/// Create a copy of BlockPhoneViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$BlockPhoneViewStateCopyWith<_BlockPhoneViewState> get copyWith => __$BlockPhoneViewStateCopyWithImpl<_BlockPhoneViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _BlockPhoneViewState&&const DeepCollectionEquality().equals(other._contacts, _contacts)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.successMessage, successMessage) || other.successMessage == successMessage)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_contacts),isLoading,isSaving,successMessage,errorMessage); + +@override +String toString() { + return 'BlockPhoneViewState(contacts: $contacts, isLoading: $isLoading, isSaving: $isSaving, successMessage: $successMessage, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class _$BlockPhoneViewStateCopyWith<$Res> implements $BlockPhoneViewStateCopyWith<$Res> { + factory _$BlockPhoneViewStateCopyWith(_BlockPhoneViewState value, $Res Function(_BlockPhoneViewState) _then) = __$BlockPhoneViewStateCopyWithImpl; +@override @useResult +$Res call({ + List contacts, bool isLoading, bool isSaving, String successMessage, String errorMessage +}); + + + + +} +/// @nodoc +class __$BlockPhoneViewStateCopyWithImpl<$Res> + implements _$BlockPhoneViewStateCopyWith<$Res> { + __$BlockPhoneViewStateCopyWithImpl(this._self, this._then); + + final _BlockPhoneViewState _self; + final $Res Function(_BlockPhoneViewState) _then; + +/// Create a copy of BlockPhoneViewState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? contacts = null,Object? isLoading = null,Object? isSaving = null,Object? successMessage = null,Object? errorMessage = null,}) { + return _then(_BlockPhoneViewState( +contacts: null == contacts ? _self._contacts : contacts // ignore: cast_nullable_to_non_nullable +as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable +as bool,successMessage: null == successMessage ? _self.successMessage : successMessage // ignore: cast_nullable_to_non_nullable +as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/widgets/add_contact_sheet.dart b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/widgets/add_contact_sheet.dart new file mode 100644 index 00000000..64ef5e48 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/widgets/add_contact_sheet.dart @@ -0,0 +1,235 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_contacts/flutter_contacts.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import 'package:settings/src/core/domain/entities/contact_list_contact_entity.dart'; + +import '../state/block_phone_view_model.dart'; + +void showAddContactSheet(BuildContext context) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (_) => const _AddContactSheet(), + ); +} + +class _AddContactSheet extends ConsumerStatefulWidget { + const _AddContactSheet(); + + @override + ConsumerState<_AddContactSheet> createState() => _AddContactSheetState(); +} + +class _AddContactSheetState extends ConsumerState<_AddContactSheet> { + final _nameController = TextEditingController(); + final _phoneController = TextEditingController(); + + @override + void dispose() { + _nameController.dispose(); + _phoneController.dispose(); + super.dispose(); + } + + bool get _canSave => + _nameController.text.trim().isNotEmpty && + _phoneController.text.trim().isNotEmpty; + + Future _pickContact() async { + final contact = await FlutterContacts.openExternalPick(); + if (contact == null || !mounted) return; + + final fullContact = await FlutterContacts.getContact( + contact.id, + withProperties: true, + ); + if (fullContact == null || fullContact.phones.isEmpty) return; + + _phoneController.text = fullContact.phones.first.number; + + if (_nameController.text.trim().isEmpty) { + _nameController.text = fullContact.displayName; + } + + setState(() {}); + } + + void _submit() { + if (!_canSave) return; + + final vm = ref.read(blockPhoneViewModelProvider.notifier); + vm.addContact( + ContactListContactEntity( + name: _nameController.text.trim(), + phone: _phoneController.text.trim(), + ), + ); + Navigator.pop(context); + } + + @override + Widget build(BuildContext context) { + final theme = ref.watch(themePortProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + final isSaving = ref.watch( + blockPhoneViewModelProvider.select((s) => s.isSaving), + ); + final bottomInset = MediaQuery.of(context).viewInsets.bottom; + + return Padding( + padding: EdgeInsets.only(bottom: bottomInset), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + child: SafeArea( + top: false, + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 22, big: 24), + vertical: SizeUtils.getByScreen(small: 16, big: 18), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey.shade300, + borderRadius: BorderRadius.circular(2), + ), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 14)), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + context.translate(I18n.addAllowedNumber), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 21), + fontWeight: FontWeight.w600, + color: primaryColor, + ), + ), + TextButton( + onPressed: _canSave && !isSaving ? _submit : null, + child: isSaving + ? SizedBox( + width: SizeUtils.getByScreen(small: 20, big: 22), + height: SizeUtils.getByScreen(small: 20, big: 22), + child: CircularProgressIndicator( + strokeWidth: 2, + color: primaryColor, + ), + ) + : Text( + context.translate(I18n.save), + style: TextStyle( + color: _canSave ? primaryColor : Colors.grey, + fontWeight: FontWeight.w600, + fontSize: + SizeUtils.getByScreen(small: 16, big: 17), + ), + ), + ), + ], + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 18)), + Text( + context.translate(I18n.name), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 16), + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 8), + TextField( + controller: _nameController, + onChanged: (_) => setState(() {}), + decoration: _inputDecoration( + hintText: context.translate(I18n.contactName), + primaryColor: primaryColor, + ), + textCapitalization: TextCapitalization.words, + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 18)), + Text( + context.translate(I18n.phone), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 16), + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 8), + Row( + children: [ + Expanded( + child: TextField( + controller: _phoneController, + onChanged: (_) => setState(() {}), + readOnly: true, + decoration: _inputDecoration( + hintText: context.translate(I18n.phoneNumber), + primaryColor: primaryColor, + ), + keyboardType: TextInputType.phone, + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 10, big: 8)), + DecoratedBox( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: primaryColor, + ), + child: IconButton( + onPressed: _pickContact, + icon: Icon( + SFIcons.contactsCircle, + color: Colors.white, + size: SizeUtils.getByScreen(small: 28, big: 26), + ), + ), + ), + ], + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 18)), + ], + ), + ), + ), + ), + ); + } + + InputDecoration _inputDecoration({ + required String hintText, + required Color primaryColor, + }) { + return InputDecoration( + hintText: hintText, + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: Colors.grey.shade300), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: Colors.grey.shade300), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: primaryColor, width: 2), + ), + contentPadding: EdgeInsets.symmetric(horizontal: 14, vertical: 14), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/widgets/whitelist_contact_card.dart b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/widgets/whitelist_contact_card.dart new file mode 100644 index 00000000..8a5d7608 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/block_phone/presentation/widgets/whitelist_contact_card.dart @@ -0,0 +1 @@ +export 'package:settings/src/core/presentation/widgets/contact_list_contact_card.dart'; diff --git a/modules/legacy/modules/settings/lib/src/features/disable_functions/disable_functions_builder.dart b/modules/legacy/modules/settings/lib/src/features/disable_functions/disable_functions_builder.dart new file mode 100644 index 00000000..dc5dff4b --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/disable_functions/disable_functions_builder.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import 'presentation/disable_functions_screen.dart'; + +class DisableFunctionsBuilder { + const DisableFunctionsBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + return MaterialPage( + key: state.pageKey, + child: const DisableFunctionsScreen(), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/disable_functions/presentation/disable_functions_screen.dart b/modules/legacy/modules/settings/lib/src/features/disable_functions/presentation/disable_functions_screen.dart new file mode 100644 index 00000000..ee13e86f --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/disable_functions/presentation/disable_functions_screen.dart @@ -0,0 +1,22 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class DisableFunctionsScreen extends ConsumerWidget { + const DisableFunctionsScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.disableFunctions), + body: const Center( + child: Text('Coming soon'), + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/language/language_builder.dart b/modules/legacy/modules/settings/lib/src/features/language/language_builder.dart new file mode 100644 index 00000000..e5fa9769 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/language/language_builder.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import 'presentation/language_screen.dart'; + +class LanguageBuilder { + const LanguageBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + return MaterialPage( + key: state.pageKey, + child: const LanguageScreen(), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/language/presentation/language_screen.dart b/modules/legacy/modules/settings/lib/src/features/language/presentation/language_screen.dart new file mode 100644 index 00000000..b31c20dd --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/language/presentation/language_screen.dart @@ -0,0 +1,22 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LanguageScreen extends ConsumerWidget { + const LanguageScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.language), + body: const Center( + child: Text('Coming soon'), + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/legacy_notifications/legacy_notifications_builder.dart b/modules/legacy/modules/settings/lib/src/features/legacy_notifications/legacy_notifications_builder.dart new file mode 100644 index 00000000..a23b0da4 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/legacy_notifications/legacy_notifications_builder.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import 'presentation/legacy_notifications_screen.dart'; + +class LegacyNotificationsBuilder { + const LegacyNotificationsBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + return MaterialPage( + key: state.pageKey, + child: const LegacyNotificationsScreen(), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/legacy_notifications/presentation/legacy_notifications_screen.dart b/modules/legacy/modules/settings/lib/src/features/legacy_notifications/presentation/legacy_notifications_screen.dart new file mode 100644 index 00000000..d517c234 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/legacy_notifications/presentation/legacy_notifications_screen.dart @@ -0,0 +1,22 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacyNotificationsScreen extends ConsumerWidget { + const LegacyNotificationsScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.legacyNotifications), + body: const Center( + child: Text('Coming soon'), + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/remote_management/presentation/state/remote_management_view_state.dart b/modules/legacy/modules/settings/lib/src/features/remote_management/presentation/state/remote_management_view_state.dart index a9e96e0a..1a51b13b 100644 --- a/modules/legacy/modules/settings/lib/src/features/remote_management/presentation/state/remote_management_view_state.dart +++ b/modules/legacy/modules/settings/lib/src/features/remote_management/presentation/state/remote_management_view_state.dart @@ -1,6 +1,4 @@ -import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:settings/src/features/alarm/domain/entities/alarm_entity.dart'; part 'remote_management_view_state.freezed.dart'; diff --git a/modules/legacy/modules/settings/lib/src/features/remote_on_off/presentation/remote_on_off_screen.dart b/modules/legacy/modules/settings/lib/src/features/remote_on_off/presentation/remote_on_off_screen.dart new file mode 100644 index 00000000..aeec695c --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/remote_on_off/presentation/remote_on_off_screen.dart @@ -0,0 +1,22 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class RemoteOnOffScreen extends ConsumerWidget { + const RemoteOnOffScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.remoteOnOff), + body: const Center( + child: Text('Coming soon'), + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/remote_on_off/remote_on_off_builder.dart b/modules/legacy/modules/settings/lib/src/features/remote_on_off/remote_on_off_builder.dart new file mode 100644 index 00000000..7b03504d --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/remote_on_off/remote_on_off_builder.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import 'presentation/remote_on_off_screen.dart'; + +class RemoteOnOffBuilder { + const RemoteOnOffBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + return MaterialPage( + key: state.pageKey, + child: const RemoteOnOffScreen(), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/settings/presentation/settings_screen.dart b/modules/legacy/modules/settings/lib/src/features/settings/presentation/settings_screen.dart index 18222c18..d24b6df8 100644 --- a/modules/legacy/modules/settings/lib/src/features/settings/presentation/settings_screen.dart +++ b/modules/legacy/modules/settings/lib/src/features/settings/presentation/settings_screen.dart @@ -7,175 +7,74 @@ import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; class SettingsScreen extends ConsumerWidget { - final NavigationContract navigationContract; - const SettingsScreen({ - super.key, - required this.navigationContract, - }); + const SettingsScreen({super.key, required this.navigationContract}); @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); + final theme = ref.watch(themePortProvider); + final color = theme.getColorFor(ThemeCode.legacyPrimary); return LegacyPageLayout( theme: theme, title: context.translate(I18n.settings), body: SingleChildScrollView( - child: Column( - children: [ - _AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.alarm);}, - icon: Icons.notifications_outlined, - text: context.translate(I18n.alarm) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){}, - icon: Icons.apps_rounded, - text: context.translate(I18n.appStore) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){}, - icon: Icons.phone_outlined, - text: context.translate(I18n.blockPhone) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){}, - icon: Icons.check, - text: context.translate(I18n.timezone) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){}, - icon: Icons.translate_outlined, - text: context.translate(I18n.language) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){}, - icon: Icons.nightlight_outlined, - text: context.translate(I18n.battery) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.remoteManagement);}, - icon: Icons.settings_remote_outlined, - text: context.translate(I18n.remoteManagement) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){}, - icon: Icons.message_outlined, - text: context.translate(I18n.legacyNotifications) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){}, - icon: Icons.sms_outlined, - text: context.translate(I18n.smsAlert) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.sosContacts);}, - icon: Icons.perm_contact_calendar_outlined, - text: context.translate(I18n.sosContacts) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.sound);}, - icon: Icons.volume_up_outlined, - text: context.translate(I18n.sound) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){}, - icon: Icons.wifi_find_outlined, - text: context.translate(I18n.wifiSettings) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){}, - icon: Icons.settings_power_outlined, - text: context.translate(I18n.remoteOnOff) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){}, - icon: Icons.dashboard_customize_outlined, - text: context.translate(I18n.disableFunctions) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - _AppSectionButton( - onPressed: (){}, - icon: Icons.share_arrival_time_outlined, - text: context.translate(I18n.syncClock) - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - ], + child: Padding( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), + big: EdgeInsets.symmetric(horizontal: 21, vertical: 8), + ), + child: Column( + children: [ + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.alarm), icon: Icons.notifications_outlined, text: I18n.alarm, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.appStore), icon: Icons.apps_rounded, text: I18n.appStore, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.blockPhone), icon: Icons.phone_outlined, text: I18n.blockPhone, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.timezone), icon: Icons.check, text: I18n.timezone, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.language), icon: Icons.translate_outlined, text: I18n.language, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.battery), icon: Icons.nightlight_outlined, text: I18n.battery, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.remoteManagement), icon: Icons.settings_remote_outlined, text: I18n.remoteManagement, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.legacyNotifications), icon: Icons.message_outlined, text: I18n.legacyNotifications, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.smsAlert), icon: Icons.sms_outlined, text: I18n.smsAlert, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.sosContacts), icon: Icons.perm_contact_calendar_outlined, text: I18n.sosContacts, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.sound), icon: Icons.volume_up_outlined, text: I18n.sound, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.wifiSettings), icon: Icons.wifi_find_outlined, text: I18n.wifiSettings, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.remoteOnOff), icon: Icons.settings_power_outlined, text: I18n.remoteOnOff, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.disableFunctions), icon: Icons.dashboard_customize_outlined, text: I18n.disableFunctions, color: color), + _item(context, onPressed: () => navigationContract.pushTo(AppRoutes.syncClock), icon: Icons.share_arrival_time_outlined, text: I18n.syncClock, color: color), + ], + ), ), - ) + ), ); } + Widget _item( + BuildContext context, { + required VoidCallback onPressed, + required IconData icon, + required String text, + required Color color, + }) { + return Padding( + padding: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 16, big: 15), + ), + child: SectionButton( + onPressed: onPressed, + icon: Icon( + icon, + size: SizeUtils.getByScreen(small: 28, big: 26), + color: color, + ), + body: Text( + context.translate(text), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 18, big: 19), + fontWeight: FontWeight.w500, + ), + ), + ), + ); + } } - -class _AppSectionButton extends ConsumerWidget { - - final GestureTapCallback onPressed; - final IconData icon; - final String text; - - const _AppSectionButton({ - required this.onPressed, - required this.icon, - required this.text, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - return GestureDetector( - onTap: onPressed, - child: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 14), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 12) - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(SizeUtils.getByScreen(small: 12, big: 18))), - color: theme.getColorFor(ThemeCode.backgroundSecondary), - ), - child: Row( - children: [ - Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: theme.getColorFor(ThemeCode.backgroundPrimary), - ), - padding: EdgeInsets.all(SizeUtils.getByScreen(small: 0, big: 0)), - child: Icon(icon, - size: SizeUtils.getByScreen(small: 52, big: 48), - color: Color(0xFF588EA5), - weight: 30, - ), - ), - SizedBox(width: SizeUtils.getByScreen(small: 16, big: 15)), - Expanded( - child: Text(context.translate(text), - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 18, big: 19), - fontWeight: FontWeight.w500 - ) - ) - ) - ], - ), - ) - ); - } -} \ No newline at end of file diff --git a/modules/legacy/modules/settings/lib/src/features/sms_alert/presentation/sms_alert_screen.dart b/modules/legacy/modules/settings/lib/src/features/sms_alert/presentation/sms_alert_screen.dart new file mode 100644 index 00000000..08960a59 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/sms_alert/presentation/sms_alert_screen.dart @@ -0,0 +1,22 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class SmsAlertScreen extends ConsumerWidget { + const SmsAlertScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.smsAlert), + body: const Center( + child: Text('Coming soon'), + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/sms_alert/sms_alert_builder.dart b/modules/legacy/modules/settings/lib/src/features/sms_alert/sms_alert_builder.dart new file mode 100644 index 00000000..2e9a9aae --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/sms_alert/sms_alert_builder.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import 'presentation/sms_alert_screen.dart'; + +class SmsAlertBuilder { + const SmsAlertBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + return MaterialPage( + key: state.pageKey, + child: const SmsAlertScreen(), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/sos_contacts/domain/set_contacts_use_case.dart b/modules/legacy/modules/settings/lib/src/features/sos_contacts/domain/set_contacts_use_case.dart deleted file mode 100644 index 727d2bf6..00000000 --- a/modules/legacy/modules/settings/lib/src/features/sos_contacts/domain/set_contacts_use_case.dart +++ /dev/null @@ -1,4 +0,0 @@ - -abstract class SetContactsUseCase { - Future setContacts({required String deviceId, required String phone}); -} diff --git a/modules/legacy/modules/settings/lib/src/features/sos_contacts/domain/set_contacts_use_case_impl.dart b/modules/legacy/modules/settings/lib/src/features/sos_contacts/domain/set_contacts_use_case_impl.dart deleted file mode 100644 index 93073ce6..00000000 --- a/modules/legacy/modules/settings/lib/src/features/sos_contacts/domain/set_contacts_use_case_impl.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:settings/src/core/domain/repositories/settings_repository.dart'; - -import 'set_contacts_use_case.dart'; - -class SetContactsUseCaseImpl implements SetContactsUseCase { - SetContactsUseCaseImpl(this._repository); - - final SettingsRepository _repository; - - @override - Future setContacts({required String deviceId, required String phone}) async { - return; - // return _repository.setContact(deviceId: deviceId, phone: phone); - } -} diff --git a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/providers/set_contacts_use_case_provider.dart b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/providers/set_contacts_use_case_provider.dart deleted file mode 100644 index ae9ebd7e..00000000 --- a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/providers/set_contacts_use_case_provider.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:settings/src/core/providers/settings_repository_provider.dart'; - -import '../../domain/set_contacts_use_case.dart'; -import '../../domain/set_contacts_use_case_impl.dart'; - -final setContactsUseCaseProvider = Provider.autoDispose((ref) { - final settingsRepository = ref.read(settingsRepositoryProvider); - return SetContactsUseCaseImpl(settingsRepository); -}); diff --git a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/sos_contacts_screen.dart b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/sos_contacts_screen.dart index ee6358a7..81b0750e 100644 --- a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/sos_contacts_screen.dart +++ b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/sos_contacts_screen.dart @@ -1,15 +1,15 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:legacy_shared/legacy_shared.dart'; import 'package:navigation/navigation.dart'; -import 'package:settings/src/features/sos_contacts/presentation/widgets/edit_phone_dialog.dart'; import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; +import '../../../core/presentation/widgets/contact_list_contact_card.dart'; import 'state/sos_contacts_view_model.dart'; +import 'widgets/add_sos_contact_sheet.dart'; class SosContactsScreen extends ConsumerWidget { - final NavigationContract navigationContract; const SosContactsScreen({ @@ -19,114 +19,242 @@ class SosContactsScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); + final theme = ref.watch(themePortProvider); + final state = ref.watch(sosContactsViewModelProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); - return LegacyPageLayout( - theme: theme, - title: context.translate(I18n.sosContacts), - body: Column( - children: [ - _ContactsSection() - ], - ), - footer: _SaveSection(), - ); - } -} - -class _ContactsSection extends ConsumerWidget { - - const _ContactsSection(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final vm = ref.read(sosContactsViewModelProvider.notifier); - - final contacts = ref.watch( - sosContactsViewModelProvider.select((s)=>s.contacts) + ref.listen( + sosContactsViewModelProvider.select((s) => s.errorMessage), + (_, errorMessage) { + if (errorMessage.isNotEmpty) { + showTopSnackbar( + context, + message: errorMessage, + type: MessageType.error, + ); + } + }, ); - return Column( - children: List.generate(contacts.length, (index) => - _ContactButton( - index: index, - phone: contacts[index] - ), - ) + ref.listen( + sosContactsViewModelProvider.select((s) => s.successMessage), + (_, successMessage) { + if (successMessage.isNotEmpty) { + showTopSnackbar( + context, + message: context.translate(successMessage), + type: MessageType.success, + ); + ref.read(sosContactsViewModelProvider.notifier).clearSuccess(); + } + }, ); - } -} -class _ContactButton extends ConsumerWidget { - - final int index; - final String phone; - - const _ContactButton({ - required this.index, - required this.phone, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - return SectionButton( - onPressed: (){showDialog(context: context, builder: (context)=>Dialog( - child: EditPhoneDialog(index: index, phone: phone) - ));}, - icon: Icon(Icons.perm_contact_calendar_outlined, - color: theme.getColorFor(ThemeCode.legacyPrimary), - size: 36, - ), - iconPadding: 8, - body: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - children: [ - Text(context.translate(I18n.number, args: {'num': index + 1}), - style: TextStyle( - fontWeight: FontWeight.w500, - fontSize: 14, - color: theme.getColorFor(ThemeCode.textPrimary) - ) - ), - Text(phone, - style: TextStyle( - fontSize: 12, - color: theme.getColorFor(ThemeCode.textTertiary) - ), - ) - ], + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + surfaceTintColor: Colors.transparent, + elevation: 0, + centerTitle: true, + automaticallyImplyLeading: false, + leading: IconButton( + onPressed: () => navigationContract.goBack(), + icon: Icon( + Icons.adaptive.arrow_back, + color: primaryColor, + size: SizeUtils.getByScreen(small: 32, big: 28), + ), + ), + title: Text( + context.translate(I18n.sosContacts).toUpperCase(), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 19), + fontWeight: FontWeight.w500, + letterSpacing: 0, + color: primaryColor, + ), + ), + actions: [ + Padding( + padding: EdgeInsets.only( + right: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: DecoratedBox( + decoration: BoxDecoration( + color: primaryColor, + shape: BoxShape.circle, + ), + child: IconButton( + onPressed: () => showAddSosContactSheet(context), + icon: Icon( + Icons.add, + color: Colors.white, + size: SizeUtils.getByScreen(small: 24, big: 22), + ), + ), + ), ), - Icon(Icons.settings_phone_outlined, - color: theme.getColorFor(ThemeCode.textTertiary), - size: 24, - ) ], - ) + ), + body: SafeArea( + top: false, + child: state.isLoading + ? const Center(child: CircularProgressIndicator()) + : state.contacts.isEmpty + ? _EmptyState(primaryColor: primaryColor) + : _ContactList(), + ), ); } } -class _SaveSection extends ConsumerWidget { +class _EmptyState extends StatelessWidget { + final Color primaryColor; - const _SaveSection(); + const _EmptyState({required this.primaryColor}); @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - final vm = ref.read(sosContactsViewModelProvider.notifier); - - return Padding( - padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12), - child: PrimaryButton( - onPressed: vm.submit, - text: context.translate(I18n.save), - color: theme.getColorFor(ThemeCode.legacyPrimary) + Widget build(BuildContext context) { + return Center( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 32, big: 30), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.emergency_outlined, + color: primaryColor, + size: SizeUtils.getByScreen(small: 120, big: 140), + ), + SizedBox(height: SizeUtils.getByScreen(small: 20, big: 24)), + Text( + context.translate(I18n.noSosContacts), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 16, big: 17), + fontWeight: FontWeight.w500, + color: Colors.grey, + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 10)), + Text( + context.translate(I18n.noSosContactsDescription), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 15), + color: Colors.grey, + ), + ), + ], + ), ), ); } -} \ No newline at end of file +} + +class _ContactList extends ConsumerWidget { + const _ContactList(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final contacts = ref.watch( + sosContactsViewModelProvider.select((s) => s.contacts), + ); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + + return SingleChildScrollView( + child: Padding( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), + big: EdgeInsets.symmetric(horizontal: 21, vertical: 8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 12, big: 10), + ), + child: Text( + context.translate(I18n.sosDescription), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 15), + color: + theme.getColorFor(ThemeCode.textPrimary).withAlpha(178), + ), + ), + ), + ...List.generate(contacts.length, (index) { + final contact = contacts[index]; + return ContactListContactCard( + contact: contact, + onDelete: () => + _confirmDelete(context, ref, index, contact.name), + theme: theme, + ); + }), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), + Text( + context.translate( + I18n.sosContactsCount, + args: {'count': contacts.length.toString()}, + ), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 14), + color: primaryColor, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ); + } + + void _confirmDelete( + BuildContext context, + WidgetRef ref, + int index, + String name, + ) { + final theme = ref.read(themePortProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(context.translate(I18n.removeSosContact)), + content: Text( + context.translate( + I18n.removeSosContactConfirm, + args: {'name': name}, + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text( + context.translate(I18n.cancel), + style: TextStyle(color: primaryColor), + ), + ), + TextButton( + onPressed: () { + ref + .read(sosContactsViewModelProvider.notifier) + .removeContact(index); + Navigator.pop(context); + }, + child: Text( + context.translate(I18n.delete), + style: TextStyle(color: Colors.red), + ), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_model.dart b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_model.dart index 677be768..53383e4b 100644 --- a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_model.dart +++ b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_model.dart @@ -1,119 +1,99 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:legacy_shared/legacy_shared.dart'; -import 'package:sf_shared/sf_shared.dart'; - -import 'sos_contacts_view_state.dart'; +import 'package:settings/src/core/domain/entities/contact_list_contact_entity.dart'; +import 'package:settings/src/core/domain/repositories/sos_contacts_repository.dart'; +import 'package:settings/src/core/providers/sos_contacts_repository_provider.dart'; +import 'package:settings/src/features/sos_contacts/presentation/state/sos_contacts_view_state.dart'; +import 'package:sf_localizations/sf_localizations.dart'; final sosContactsViewModelProvider = -NotifierProvider.autoDispose( + NotifierProvider.autoDispose( SosContactsViewModel.new, ); class SosContactsViewModel extends Notifier { - - static final RegExp _phoneRegex = RegExp(r'^\+?\d{6,15}$'); - - // late final SetContactsUseCase _setContactsUseCase; - late final TextEditingController phoneController; + late final SosContactsRepository _repository; @override SosContactsViewState build() { - // _setContactsUseCase = ref.read(setContactsUseCaseProvider); - - phoneController = TextEditingController(); - phoneController.addListener(_onPhoneChanged); - - Future.microtask(() => load()); - + _repository = ref.read(sosContactsRepositoryProvider); + Future.microtask(_load); return const SosContactsViewState(); } - Future load() async { - final device = ref.read(selectedDeviceProvider); - - setDevice(device!); - } - - void setDevice(DeviceEntity device) { - state = state.copyWith( - deviceId: device.identificator, - isLoading: false, - ); - } - - void _onPhoneChanged() { - final value = phoneController.text; - - if (value == state.phone) return; - - state = state.copyWith( - phone: value, - errorMessage: '', - ); - } - - void setContactPhone(int index) { - List contacts = state.contacts.toList(); - final phone = state.phone; - - if (phone.isEmpty){ - state = state.copyWith(errorMessage: 'errorMessagePhoneIsEmpty'); - return; - } - if (!_phoneRegex.hasMatch(phone)) { - state = state.copyWith(errorMessage: 'errorMessagePhoneIsInvalid'); - return; - } - - contacts[index] = phone; - - phoneController.text = ''; - state = state.copyWith( - contacts: contacts, - phone: '', - ); - } - - Future submit() async { + Future _load() async { try { - state = state.copyWith( - isLoading: true, - ); - // _setContactsUseCase.setContacts(); + final device = ref.read(selectedDeviceProvider); + if (device == null) return; + + final contacts = + await _repository.getEmergencyContacts(deviceId: device.id); + state = state.copyWith(contacts: contacts, isLoading: false); } catch (e) { state = state.copyWith( isLoading: false, - errorMessage: e.toString() + errorMessage: formatErrorMessage(e), ); } } - Future restart() async { + Future addContact(ContactListContactEntity contact) async { + state = state.copyWith(isSaving: true, errorMessage: ''); + try { - state = state.copyWith( - isLoading: true, + final device = ref.read(selectedDeviceProvider); + if (device == null) return; + + final updatedContacts = [...state.contacts, contact]; + + await _repository.upsertEmergencyContacts( + userId: device.userId ?? '', + deviceId: device.id, + contacts: updatedContacts, + ); + + state = state.copyWith( + contacts: updatedContacts, + isSaving: false, + successMessage: I18n.sosNumberAdded, ); - // _restartUseCase.restart(); } catch (e) { state = state.copyWith( - isLoading: false, - errorMessage: e.toString() + isSaving: false, + errorMessage: formatErrorMessage(e), ); } } - Future factoryReset() async { + Future removeContact(int index) async { + state = state.copyWith(isSaving: true, errorMessage: ''); + try { - state = state.copyWith( - isLoading: true, + final device = ref.read(selectedDeviceProvider); + if (device == null) return; + + final updatedContacts = [...state.contacts]..removeAt(index); + + await _repository.upsertEmergencyContacts( + userId: device.userId ?? '', + deviceId: device.id, + contacts: updatedContacts, + ); + + state = state.copyWith( + contacts: updatedContacts, + isSaving: false, + successMessage: I18n.sosNumberRemoved, ); - // _factoryResetUseCase.fatoryReset(); } catch (e) { state = state.copyWith( - isLoading: false, - errorMessage: e.toString() + isSaving: false, + errorMessage: formatErrorMessage(e), ); } } + + void clearSuccess() { + state = state.copyWith(successMessage: ''); + } } diff --git a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_state.dart b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_state.dart index 12de61b5..7d33ccf1 100644 --- a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_state.dart +++ b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_state.dart @@ -1,17 +1,15 @@ -import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:legacy_shared/legacy_shared.dart'; -import 'package:settings/src/features/alarm/domain/entities/alarm_entity.dart'; +import 'package:settings/src/core/domain/entities/contact_list_contact_entity.dart'; part 'sos_contacts_view_state.freezed.dart'; @freezed abstract class SosContactsViewState with _$SosContactsViewState { const factory SosContactsViewState({ - @Default('') String deviceId, - @Default(['', '', '']) List contacts, - @Default('') String phone, + @Default([]) List contacts, @Default(true) bool isLoading, + @Default(false) bool isSaving, + @Default('') String successMessage, @Default('') String errorMessage, }) = _SosContactsViewState; } diff --git a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_state.freezed.dart b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_state.freezed.dart index c5e429b3..729b0f0c 100644 --- a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_state.freezed.dart +++ b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/state/sos_contacts_view_state.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$SosContactsViewState { - String get deviceId; List get contacts; String get phone; bool get isLoading; String get errorMessage; + List get contacts; bool get isLoading; bool get isSaving; String get successMessage; String get errorMessage; /// Create a copy of SosContactsViewState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $SosContactsViewStateCopyWith get copyWith => _$SosContact @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is SosContactsViewState&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&const DeepCollectionEquality().equals(other.contacts, contacts)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is SosContactsViewState&&const DeepCollectionEquality().equals(other.contacts, contacts)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.successMessage, successMessage) || other.successMessage == successMessage)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,deviceId,const DeepCollectionEquality().hash(contacts),phone,isLoading,errorMessage); +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(contacts),isLoading,isSaving,successMessage,errorMessage); @override String toString() { - return 'SosContactsViewState(deviceId: $deviceId, contacts: $contacts, phone: $phone, isLoading: $isLoading, errorMessage: $errorMessage)'; + return 'SosContactsViewState(contacts: $contacts, isLoading: $isLoading, isSaving: $isSaving, successMessage: $successMessage, errorMessage: $errorMessage)'; } @@ -45,7 +45,7 @@ abstract mixin class $SosContactsViewStateCopyWith<$Res> { factory $SosContactsViewStateCopyWith(SosContactsViewState value, $Res Function(SosContactsViewState) _then) = _$SosContactsViewStateCopyWithImpl; @useResult $Res call({ - String deviceId, List contacts, String phone, bool isLoading, String errorMessage + List contacts, bool isLoading, bool isSaving, String successMessage, String errorMessage }); @@ -62,13 +62,13 @@ class _$SosContactsViewStateCopyWithImpl<$Res> /// Create a copy of SosContactsViewState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? deviceId = null,Object? contacts = null,Object? phone = null,Object? isLoading = null,Object? errorMessage = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? contacts = null,Object? isLoading = null,Object? isSaving = null,Object? successMessage = null,Object? errorMessage = null,}) { return _then(_self.copyWith( -deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable -as String,contacts: null == contacts ? _self.contacts : contacts // ignore: cast_nullable_to_non_nullable -as List,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable -as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable -as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +contacts: null == contacts ? _self.contacts : contacts // ignore: cast_nullable_to_non_nullable +as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable +as bool,successMessage: null == successMessage ? _self.successMessage : successMessage // ignore: cast_nullable_to_non_nullable +as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String, )); } @@ -154,10 +154,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String deviceId, List contacts, String phone, bool isLoading, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( List contacts, bool isLoading, bool isSaving, String successMessage, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _SosContactsViewState() when $default != null: -return $default(_that.deviceId,_that.contacts,_that.phone,_that.isLoading,_that.errorMessage);case _: +return $default(_that.contacts,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: return orElse(); } @@ -175,10 +175,10 @@ return $default(_that.deviceId,_that.contacts,_that.phone,_that.isLoading,_that. /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String deviceId, List contacts, String phone, bool isLoading, String errorMessage) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( List contacts, bool isLoading, bool isSaving, String successMessage, String errorMessage) $default,) {final _that = this; switch (_that) { case _SosContactsViewState(): -return $default(_that.deviceId,_that.contacts,_that.phone,_that.isLoading,_that.errorMessage);case _: +return $default(_that.contacts,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: throw StateError('Unexpected subclass'); } @@ -195,10 +195,10 @@ return $default(_that.deviceId,_that.contacts,_that.phone,_that.isLoading,_that. /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String deviceId, List contacts, String phone, bool isLoading, String errorMessage)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List contacts, bool isLoading, bool isSaving, String successMessage, String errorMessage)? $default,) {final _that = this; switch (_that) { case _SosContactsViewState() when $default != null: -return $default(_that.deviceId,_that.contacts,_that.phone,_that.isLoading,_that.errorMessage);case _: +return $default(_that.contacts,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: return null; } @@ -210,19 +210,19 @@ return $default(_that.deviceId,_that.contacts,_that.phone,_that.isLoading,_that. class _SosContactsViewState implements SosContactsViewState { - const _SosContactsViewState({this.deviceId = '', final List contacts = const ['', '', ''], this.phone = '', this.isLoading = true, this.errorMessage = ''}): _contacts = contacts; + const _SosContactsViewState({final List contacts = const [], this.isLoading = true, this.isSaving = false, this.successMessage = '', this.errorMessage = ''}): _contacts = contacts; -@override@JsonKey() final String deviceId; - final List _contacts; -@override@JsonKey() List get contacts { + final List _contacts; +@override@JsonKey() List get contacts { if (_contacts is EqualUnmodifiableListView) return _contacts; // ignore: implicit_dynamic_type return EqualUnmodifiableListView(_contacts); } -@override@JsonKey() final String phone; @override@JsonKey() final bool isLoading; +@override@JsonKey() final bool isSaving; +@override@JsonKey() final String successMessage; @override@JsonKey() final String errorMessage; /// Create a copy of SosContactsViewState @@ -235,16 +235,16 @@ _$SosContactsViewStateCopyWith<_SosContactsViewState> get copyWith => __$SosCont @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _SosContactsViewState&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&const DeepCollectionEquality().equals(other._contacts, _contacts)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SosContactsViewState&&const DeepCollectionEquality().equals(other._contacts, _contacts)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.successMessage, successMessage) || other.successMessage == successMessage)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,deviceId,const DeepCollectionEquality().hash(_contacts),phone,isLoading,errorMessage); +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_contacts),isLoading,isSaving,successMessage,errorMessage); @override String toString() { - return 'SosContactsViewState(deviceId: $deviceId, contacts: $contacts, phone: $phone, isLoading: $isLoading, errorMessage: $errorMessage)'; + return 'SosContactsViewState(contacts: $contacts, isLoading: $isLoading, isSaving: $isSaving, successMessage: $successMessage, errorMessage: $errorMessage)'; } @@ -255,7 +255,7 @@ abstract mixin class _$SosContactsViewStateCopyWith<$Res> implements $SosContact factory _$SosContactsViewStateCopyWith(_SosContactsViewState value, $Res Function(_SosContactsViewState) _then) = __$SosContactsViewStateCopyWithImpl; @override @useResult $Res call({ - String deviceId, List contacts, String phone, bool isLoading, String errorMessage + List contacts, bool isLoading, bool isSaving, String successMessage, String errorMessage }); @@ -272,13 +272,13 @@ class __$SosContactsViewStateCopyWithImpl<$Res> /// Create a copy of SosContactsViewState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? deviceId = null,Object? contacts = null,Object? phone = null,Object? isLoading = null,Object? errorMessage = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? contacts = null,Object? isLoading = null,Object? isSaving = null,Object? successMessage = null,Object? errorMessage = null,}) { return _then(_SosContactsViewState( -deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable -as String,contacts: null == contacts ? _self._contacts : contacts // ignore: cast_nullable_to_non_nullable -as List,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable -as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable -as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +contacts: null == contacts ? _self._contacts : contacts // ignore: cast_nullable_to_non_nullable +as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable +as bool,successMessage: null == successMessage ? _self.successMessage : successMessage // ignore: cast_nullable_to_non_nullable +as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String, )); } diff --git a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/widgets/add_sos_contact_sheet.dart b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/widgets/add_sos_contact_sheet.dart new file mode 100644 index 00000000..c1324258 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/widgets/add_sos_contact_sheet.dart @@ -0,0 +1,236 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_contacts/flutter_contacts.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import 'package:settings/src/core/domain/entities/contact_list_contact_entity.dart'; + +import '../state/sos_contacts_view_model.dart'; + +void showAddSosContactSheet(BuildContext context) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (_) => const _AddSosContactSheet(), + ); +} + +class _AddSosContactSheet extends ConsumerStatefulWidget { + const _AddSosContactSheet(); + + @override + ConsumerState<_AddSosContactSheet> createState() => + _AddSosContactSheetState(); +} + +class _AddSosContactSheetState extends ConsumerState<_AddSosContactSheet> { + final _nameController = TextEditingController(); + final _phoneController = TextEditingController(); + + @override + void dispose() { + _nameController.dispose(); + _phoneController.dispose(); + super.dispose(); + } + + bool get _canSave => + _nameController.text.trim().isNotEmpty && + _phoneController.text.trim().isNotEmpty; + + Future _pickContact() async { + final contact = await FlutterContacts.openExternalPick(); + if (contact == null || !mounted) return; + + final fullContact = await FlutterContacts.getContact( + contact.id, + withProperties: true, + ); + if (fullContact == null || fullContact.phones.isEmpty) return; + + _phoneController.text = fullContact.phones.first.number; + + if (_nameController.text.trim().isEmpty) { + _nameController.text = fullContact.displayName; + } + + setState(() {}); + } + + void _submit() { + if (!_canSave) return; + + final vm = ref.read(sosContactsViewModelProvider.notifier); + vm.addContact( + ContactListContactEntity( + name: _nameController.text.trim(), + phone: _phoneController.text.trim(), + ), + ); + Navigator.pop(context); + } + + @override + Widget build(BuildContext context) { + final theme = ref.watch(themePortProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + final isSaving = ref.watch( + sosContactsViewModelProvider.select((s) => s.isSaving), + ); + final bottomInset = MediaQuery.of(context).viewInsets.bottom; + + return Padding( + padding: EdgeInsets.only(bottom: bottomInset), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + child: SafeArea( + top: false, + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 22, big: 24), + vertical: SizeUtils.getByScreen(small: 16, big: 18), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey.shade300, + borderRadius: BorderRadius.circular(2), + ), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 14)), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + context.translate(I18n.addSosContact), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 21), + fontWeight: FontWeight.w600, + color: primaryColor, + ), + ), + TextButton( + onPressed: _canSave && !isSaving ? _submit : null, + child: isSaving + ? SizedBox( + width: SizeUtils.getByScreen(small: 20, big: 22), + height: SizeUtils.getByScreen(small: 20, big: 22), + child: CircularProgressIndicator( + strokeWidth: 2, + color: primaryColor, + ), + ) + : Text( + context.translate(I18n.save), + style: TextStyle( + color: _canSave ? primaryColor : Colors.grey, + fontWeight: FontWeight.w600, + fontSize: + SizeUtils.getByScreen(small: 16, big: 17), + ), + ), + ), + ], + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 18)), + Text( + context.translate(I18n.name), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 16), + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 8), + TextField( + controller: _nameController, + onChanged: (_) => setState(() {}), + decoration: _inputDecoration( + hintText: context.translate(I18n.contactName), + primaryColor: primaryColor, + ), + textCapitalization: TextCapitalization.words, + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 18)), + Text( + context.translate(I18n.phone), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 16), + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 8), + Row( + children: [ + Expanded( + child: TextField( + controller: _phoneController, + onChanged: (_) => setState(() {}), + readOnly: true, + decoration: _inputDecoration( + hintText: context.translate(I18n.phoneNumber), + primaryColor: primaryColor, + ), + keyboardType: TextInputType.phone, + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 10, big: 8)), + DecoratedBox( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: primaryColor, + ), + child: IconButton( + onPressed: _pickContact, + icon: Icon( + SFIcons.contactsCircle, + color: Colors.white, + size: SizeUtils.getByScreen(small: 28, big: 26), + ), + ), + ), + ], + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 18)), + ], + ), + ), + ), + ), + ); + } + + InputDecoration _inputDecoration({ + required String hintText, + required Color primaryColor, + }) { + return InputDecoration( + hintText: hintText, + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: Colors.grey.shade300), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: Colors.grey.shade300), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: primaryColor, width: 2), + ), + contentPadding: EdgeInsets.symmetric(horizontal: 14, vertical: 14), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/widgets/edit_phone_dialog.dart b/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/widgets/edit_phone_dialog.dart deleted file mode 100644 index 6fd773a2..00000000 --- a/modules/legacy/modules/settings/lib/src/features/sos_contacts/presentation/widgets/edit_phone_dialog.dart +++ /dev/null @@ -1,92 +0,0 @@ -import 'package:design_system/design_system.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:settings/src/features/sos_contacts/presentation/state/sos_contacts_view_model.dart'; -import 'package:sf_localizations/sf_localizations.dart'; - -class EditPhoneDialog extends ConsumerWidget { - - final int index; - final String phone; - - const EditPhoneDialog({ - required this.index, - required this.phone, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - final vm = ref.read(sosContactsViewModelProvider.notifier); - final errorMessage = ref.watch( - sosContactsViewModelProvider.select((s)=>s.errorMessage) - ); - - return Container( - decoration: BoxDecoration( - color: theme.getColorFor(ThemeCode.backgroundPrimary), - borderRadius: BorderRadius.all(Radius.circular(10)), - ), - padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12), - height: 220, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Stack( - children: [ - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: (){Navigator.pop(context);}, - icon: Icon(Icons.close, - color: theme.getColorFor(ThemeCode.legacyPrimary) - ) - ), - ), - Center( - child: Text( - context.translate(I18n.number, args: {'num': index + 1}).toUpperCase(), - style: TextStyle( - fontWeight: FontWeight.w500, - fontSize: 16, - color: theme.getColorFor(ThemeCode.legacyPrimary), - ), - ), - ), - ], - ), - CustomTextField( - controller: vm.phoneController, - keyboardType: TextInputType.phone, - hint: context.translate(I18n.insertPhone), - ), - if (errorMessage.isNotEmpty) ...[ - const SizedBox(height: 8), - Text( - errorMessage, - style: const TextStyle(color: Colors.red, fontSize: 13), - textAlign: TextAlign.center, - ), - ], - PrimaryButton( - onPressed: (){ - vm.setContactPhone(index); - - final errorMessage = ref.read( - sosContactsViewModelProvider.select((s)=>s.errorMessage) - ); - - if (errorMessage.isEmpty){ - Navigator.pop(context); - } - }, - text: context.translate(I18n.save), - color: theme.getColorFor(ThemeCode.legacyPrimary) - ) - ], - ), - ); - } -} \ No newline at end of file diff --git a/modules/legacy/modules/settings/lib/src/features/timezone/presentation/timezone_screen.dart b/modules/legacy/modules/settings/lib/src/features/timezone/presentation/timezone_screen.dart new file mode 100644 index 00000000..309bf503 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/timezone/presentation/timezone_screen.dart @@ -0,0 +1,22 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class TimezoneScreen extends ConsumerWidget { + const TimezoneScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.timezone), + body: const Center( + child: Text('Coming soon'), + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/timezone/timezone_builder.dart b/modules/legacy/modules/settings/lib/src/features/timezone/timezone_builder.dart new file mode 100644 index 00000000..12526362 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/timezone/timezone_builder.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import 'presentation/timezone_screen.dart'; + +class TimezoneBuilder { + const TimezoneBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + return MaterialPage( + key: state.pageKey, + child: const TimezoneScreen(), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/wifi_settings/domain/entities/wifi_network_entity.dart b/modules/legacy/modules/settings/lib/src/features/wifi_settings/domain/entities/wifi_network_entity.dart new file mode 100644 index 00000000..f833409b --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/wifi_settings/domain/entities/wifi_network_entity.dart @@ -0,0 +1,12 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'wifi_network_entity.freezed.dart'; + +@freezed +abstract class WifiNetworkEntity with _$WifiNetworkEntity { + const factory WifiNetworkEntity({ + required String id, + required String ssid, + required String bssid, + }) = _WifiNetworkEntity; +} diff --git a/modules/legacy/modules/settings/lib/src/features/wifi_settings/domain/entities/wifi_network_entity.freezed.dart b/modules/legacy/modules/settings/lib/src/features/wifi_settings/domain/entities/wifi_network_entity.freezed.dart new file mode 100644 index 00000000..45c0538d --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/wifi_settings/domain/entities/wifi_network_entity.freezed.dart @@ -0,0 +1,277 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'wifi_network_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$WifiNetworkEntity { + + String get id; String get ssid; String get bssid; +/// Create a copy of WifiNetworkEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$WifiNetworkEntityCopyWith get copyWith => _$WifiNetworkEntityCopyWithImpl(this as WifiNetworkEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is WifiNetworkEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.ssid, ssid) || other.ssid == ssid)&&(identical(other.bssid, bssid) || other.bssid == bssid)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,ssid,bssid); + +@override +String toString() { + return 'WifiNetworkEntity(id: $id, ssid: $ssid, bssid: $bssid)'; +} + + +} + +/// @nodoc +abstract mixin class $WifiNetworkEntityCopyWith<$Res> { + factory $WifiNetworkEntityCopyWith(WifiNetworkEntity value, $Res Function(WifiNetworkEntity) _then) = _$WifiNetworkEntityCopyWithImpl; +@useResult +$Res call({ + String id, String ssid, String bssid +}); + + + + +} +/// @nodoc +class _$WifiNetworkEntityCopyWithImpl<$Res> + implements $WifiNetworkEntityCopyWith<$Res> { + _$WifiNetworkEntityCopyWithImpl(this._self, this._then); + + final WifiNetworkEntity _self; + final $Res Function(WifiNetworkEntity) _then; + +/// Create a copy of WifiNetworkEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? ssid = null,Object? bssid = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,ssid: null == ssid ? _self.ssid : ssid // ignore: cast_nullable_to_non_nullable +as String,bssid: null == bssid ? _self.bssid : bssid // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [WifiNetworkEntity]. +extension WifiNetworkEntityPatterns on WifiNetworkEntity { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _WifiNetworkEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _WifiNetworkEntity() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _WifiNetworkEntity value) $default,){ +final _that = this; +switch (_that) { +case _WifiNetworkEntity(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _WifiNetworkEntity value)? $default,){ +final _that = this; +switch (_that) { +case _WifiNetworkEntity() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String ssid, String bssid)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _WifiNetworkEntity() when $default != null: +return $default(_that.id,_that.ssid,_that.bssid);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String ssid, String bssid) $default,) {final _that = this; +switch (_that) { +case _WifiNetworkEntity(): +return $default(_that.id,_that.ssid,_that.bssid);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String ssid, String bssid)? $default,) {final _that = this; +switch (_that) { +case _WifiNetworkEntity() when $default != null: +return $default(_that.id,_that.ssid,_that.bssid);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _WifiNetworkEntity implements WifiNetworkEntity { + const _WifiNetworkEntity({required this.id, required this.ssid, required this.bssid}); + + +@override final String id; +@override final String ssid; +@override final String bssid; + +/// Create a copy of WifiNetworkEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$WifiNetworkEntityCopyWith<_WifiNetworkEntity> get copyWith => __$WifiNetworkEntityCopyWithImpl<_WifiNetworkEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _WifiNetworkEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.ssid, ssid) || other.ssid == ssid)&&(identical(other.bssid, bssid) || other.bssid == bssid)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,ssid,bssid); + +@override +String toString() { + return 'WifiNetworkEntity(id: $id, ssid: $ssid, bssid: $bssid)'; +} + + +} + +/// @nodoc +abstract mixin class _$WifiNetworkEntityCopyWith<$Res> implements $WifiNetworkEntityCopyWith<$Res> { + factory _$WifiNetworkEntityCopyWith(_WifiNetworkEntity value, $Res Function(_WifiNetworkEntity) _then) = __$WifiNetworkEntityCopyWithImpl; +@override @useResult +$Res call({ + String id, String ssid, String bssid +}); + + + + +} +/// @nodoc +class __$WifiNetworkEntityCopyWithImpl<$Res> + implements _$WifiNetworkEntityCopyWith<$Res> { + __$WifiNetworkEntityCopyWithImpl(this._self, this._then); + + final _WifiNetworkEntity _self; + final $Res Function(_WifiNetworkEntity) _then; + +/// Create a copy of WifiNetworkEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? ssid = null,Object? bssid = null,}) { + return _then(_WifiNetworkEntity( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,ssid: null == ssid ? _self.ssid : ssid // ignore: cast_nullable_to_non_nullable +as String,bssid: null == bssid ? _self.bssid : bssid // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/state/wifi_settings_view_model.dart b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/state/wifi_settings_view_model.dart new file mode 100644 index 00000000..cbe4070d --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/state/wifi_settings_view_model.dart @@ -0,0 +1,100 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:legacy_shared/legacy_shared.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +import '../../../../core/domain/repositories/wifi_repository.dart'; +import '../../../../core/providers/wifi_repository_provider.dart'; +import 'wifi_settings_view_state.dart'; + +final wifiSettingsViewModelProvider = + NotifierProvider.autoDispose( + WifiSettingsViewModel.new, +); + +class WifiSettingsViewModel extends Notifier { + late final WifiRepository _repository; + + @override + WifiSettingsViewState build() { + _repository = ref.read(wifiRepositoryProvider); + Future.microtask(_load); + return const WifiSettingsViewState(); + } + + Future _load() async { + try { + final device = ref.read(selectedDeviceProvider); + if (device == null) return; + + final networks = + await _repository.getWifiNetworks(deviceId: device.id); + state = state.copyWith(networks: networks, isLoading: false); + } catch (e) { + state = state.copyWith( + isLoading: false, + errorMessage: formatErrorMessage(e), + ); + } + } + + Future addNetwork({ + required String ssid, + required String bssid, + }) async { + state = state.copyWith(isSaving: true, errorMessage: ''); + + try { + final device = ref.read(selectedDeviceProvider); + if (device == null) return; + + await _repository.createWifiNetwork( + deviceId: device.id, + ssid: ssid, + bssid: bssid, + ); + + final networks = + await _repository.getWifiNetworks(deviceId: device.id); + + state = state.copyWith( + networks: networks, + isSaving: false, + successMessage: I18n.wifiNetworkAdded, + ); + } catch (e) { + state = state.copyWith( + isSaving: false, + errorMessage: formatErrorMessage(e), + ); + } + } + + Future removeNetwork(String networkId) async { + state = state.copyWith(isSaving: true, errorMessage: ''); + + try { + final device = ref.read(selectedDeviceProvider); + if (device == null) return; + + await _repository.deleteWifiNetwork(networkId: networkId); + + final networks = + await _repository.getWifiNetworks(deviceId: device.id); + + state = state.copyWith( + networks: networks, + isSaving: false, + successMessage: I18n.wifiNetworkRemoved, + ); + } catch (e) { + state = state.copyWith( + isSaving: false, + errorMessage: formatErrorMessage(e), + ); + } + } + + void clearSuccess() { + state = state.copyWith(successMessage: ''); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/state/wifi_settings_view_state.dart b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/state/wifi_settings_view_state.dart new file mode 100644 index 00000000..0d9ecec5 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/state/wifi_settings_view_state.dart @@ -0,0 +1,16 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../domain/entities/wifi_network_entity.dart'; + +part 'wifi_settings_view_state.freezed.dart'; + +@freezed +abstract class WifiSettingsViewState with _$WifiSettingsViewState { + const factory WifiSettingsViewState({ + @Default([]) List networks, + @Default(true) bool isLoading, + @Default(false) bool isSaving, + @Default('') String successMessage, + @Default('') String errorMessage, + }) = _WifiSettingsViewState; +} diff --git a/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/state/wifi_settings_view_state.freezed.dart b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/state/wifi_settings_view_state.freezed.dart new file mode 100644 index 00000000..74aaf812 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/state/wifi_settings_view_state.freezed.dart @@ -0,0 +1,289 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'wifi_settings_view_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$WifiSettingsViewState { + + List get networks; bool get isLoading; bool get isSaving; String get successMessage; String get errorMessage; +/// Create a copy of WifiSettingsViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$WifiSettingsViewStateCopyWith get copyWith => _$WifiSettingsViewStateCopyWithImpl(this as WifiSettingsViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is WifiSettingsViewState&&const DeepCollectionEquality().equals(other.networks, networks)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.successMessage, successMessage) || other.successMessage == successMessage)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(networks),isLoading,isSaving,successMessage,errorMessage); + +@override +String toString() { + return 'WifiSettingsViewState(networks: $networks, isLoading: $isLoading, isSaving: $isSaving, successMessage: $successMessage, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class $WifiSettingsViewStateCopyWith<$Res> { + factory $WifiSettingsViewStateCopyWith(WifiSettingsViewState value, $Res Function(WifiSettingsViewState) _then) = _$WifiSettingsViewStateCopyWithImpl; +@useResult +$Res call({ + List networks, bool isLoading, bool isSaving, String successMessage, String errorMessage +}); + + + + +} +/// @nodoc +class _$WifiSettingsViewStateCopyWithImpl<$Res> + implements $WifiSettingsViewStateCopyWith<$Res> { + _$WifiSettingsViewStateCopyWithImpl(this._self, this._then); + + final WifiSettingsViewState _self; + final $Res Function(WifiSettingsViewState) _then; + +/// Create a copy of WifiSettingsViewState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? networks = null,Object? isLoading = null,Object? isSaving = null,Object? successMessage = null,Object? errorMessage = null,}) { + return _then(_self.copyWith( +networks: null == networks ? _self.networks : networks // ignore: cast_nullable_to_non_nullable +as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable +as bool,successMessage: null == successMessage ? _self.successMessage : successMessage // ignore: cast_nullable_to_non_nullable +as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [WifiSettingsViewState]. +extension WifiSettingsViewStatePatterns on WifiSettingsViewState { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _WifiSettingsViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _WifiSettingsViewState() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _WifiSettingsViewState value) $default,){ +final _that = this; +switch (_that) { +case _WifiSettingsViewState(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _WifiSettingsViewState value)? $default,){ +final _that = this; +switch (_that) { +case _WifiSettingsViewState() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( List networks, bool isLoading, bool isSaving, String successMessage, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _WifiSettingsViewState() when $default != null: +return $default(_that.networks,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( List networks, bool isLoading, bool isSaving, String successMessage, String errorMessage) $default,) {final _that = this; +switch (_that) { +case _WifiSettingsViewState(): +return $default(_that.networks,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List networks, bool isLoading, bool isSaving, String successMessage, String errorMessage)? $default,) {final _that = this; +switch (_that) { +case _WifiSettingsViewState() when $default != null: +return $default(_that.networks,_that.isLoading,_that.isSaving,_that.successMessage,_that.errorMessage);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _WifiSettingsViewState implements WifiSettingsViewState { + const _WifiSettingsViewState({final List networks = const [], this.isLoading = true, this.isSaving = false, this.successMessage = '', this.errorMessage = ''}): _networks = networks; + + + final List _networks; +@override@JsonKey() List get networks { + if (_networks is EqualUnmodifiableListView) return _networks; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_networks); +} + +@override@JsonKey() final bool isLoading; +@override@JsonKey() final bool isSaving; +@override@JsonKey() final String successMessage; +@override@JsonKey() final String errorMessage; + +/// Create a copy of WifiSettingsViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$WifiSettingsViewStateCopyWith<_WifiSettingsViewState> get copyWith => __$WifiSettingsViewStateCopyWithImpl<_WifiSettingsViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _WifiSettingsViewState&&const DeepCollectionEquality().equals(other._networks, _networks)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.successMessage, successMessage) || other.successMessage == successMessage)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_networks),isLoading,isSaving,successMessage,errorMessage); + +@override +String toString() { + return 'WifiSettingsViewState(networks: $networks, isLoading: $isLoading, isSaving: $isSaving, successMessage: $successMessage, errorMessage: $errorMessage)'; +} + + +} + +/// @nodoc +abstract mixin class _$WifiSettingsViewStateCopyWith<$Res> implements $WifiSettingsViewStateCopyWith<$Res> { + factory _$WifiSettingsViewStateCopyWith(_WifiSettingsViewState value, $Res Function(_WifiSettingsViewState) _then) = __$WifiSettingsViewStateCopyWithImpl; +@override @useResult +$Res call({ + List networks, bool isLoading, bool isSaving, String successMessage, String errorMessage +}); + + + + +} +/// @nodoc +class __$WifiSettingsViewStateCopyWithImpl<$Res> + implements _$WifiSettingsViewStateCopyWith<$Res> { + __$WifiSettingsViewStateCopyWithImpl(this._self, this._then); + + final _WifiSettingsViewState _self; + final $Res Function(_WifiSettingsViewState) _then; + +/// Create a copy of WifiSettingsViewState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? networks = null,Object? isLoading = null,Object? isSaving = null,Object? successMessage = null,Object? errorMessage = null,}) { + return _then(_WifiSettingsViewState( +networks: null == networks ? _self._networks : networks // ignore: cast_nullable_to_non_nullable +as List,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable +as bool,successMessage: null == successMessage ? _self.successMessage : successMessage // ignore: cast_nullable_to_non_nullable +as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/widgets/add_wifi_network_sheet.dart b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/widgets/add_wifi_network_sheet.dart new file mode 100644 index 00000000..907b8dc8 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/widgets/add_wifi_network_sheet.dart @@ -0,0 +1,188 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import '../state/wifi_settings_view_model.dart'; + +void showAddWifiNetworkSheet(BuildContext context) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (_) => const _AddWifiNetworkSheet(), + ); +} + +class _AddWifiNetworkSheet extends ConsumerStatefulWidget { + const _AddWifiNetworkSheet(); + + @override + ConsumerState<_AddWifiNetworkSheet> createState() => + _AddWifiNetworkSheetState(); +} + +class _AddWifiNetworkSheetState extends ConsumerState<_AddWifiNetworkSheet> { + final _ssidController = TextEditingController(); + final _bssidController = TextEditingController(); + + @override + void dispose() { + _ssidController.dispose(); + _bssidController.dispose(); + super.dispose(); + } + + bool get _canSave => + _ssidController.text.trim().isNotEmpty && + _bssidController.text.trim().isNotEmpty; + + void _submit() { + if (!_canSave) return; + + final vm = ref.read(wifiSettingsViewModelProvider.notifier); + vm.addNetwork( + ssid: _ssidController.text.trim(), + bssid: _bssidController.text.trim(), + ); + Navigator.pop(context); + } + + @override + Widget build(BuildContext context) { + final theme = ref.watch(themePortProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + final isSaving = ref.watch( + wifiSettingsViewModelProvider.select((s) => s.isSaving), + ); + final bottomInset = MediaQuery.of(context).viewInsets.bottom; + + return Padding( + padding: EdgeInsets.only(bottom: bottomInset), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + child: SafeArea( + top: false, + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 22, big: 24), + vertical: SizeUtils.getByScreen(small: 16, big: 18), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey.shade300, + borderRadius: BorderRadius.circular(2), + ), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 14)), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + context.translate(I18n.addWifiNetwork), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 21), + fontWeight: FontWeight.w600, + color: primaryColor, + ), + ), + TextButton( + onPressed: _canSave && !isSaving ? _submit : null, + child: isSaving + ? SizedBox( + width: SizeUtils.getByScreen(small: 20, big: 22), + height: SizeUtils.getByScreen(small: 20, big: 22), + child: CircularProgressIndicator( + strokeWidth: 2, + color: primaryColor, + ), + ) + : Text( + context.translate(I18n.save), + style: TextStyle( + color: _canSave ? primaryColor : Colors.grey, + fontWeight: FontWeight.w600, + fontSize: + SizeUtils.getByScreen(small: 16, big: 17), + ), + ), + ), + ], + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 18)), + Text( + context.translate(I18n.wifiSsid), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 16), + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 8), + TextField( + controller: _ssidController, + onChanged: (_) => setState(() {}), + decoration: _inputDecoration( + hintText: context.translate(I18n.wifiSsidHint), + primaryColor: primaryColor, + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 18)), + Text( + context.translate(I18n.wifiBssid), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 15, big: 16), + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 8), + TextField( + controller: _bssidController, + onChanged: (_) => setState(() {}), + decoration: _inputDecoration( + hintText: context.translate(I18n.wifiBssidHint), + primaryColor: primaryColor, + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 18)), + ], + ), + ), + ), + ), + ); + } + + InputDecoration _inputDecoration({ + required String hintText, + required Color primaryColor, + }) { + return InputDecoration( + hintText: hintText, + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: Colors.grey.shade300), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: Colors.grey.shade300), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + borderSide: BorderSide(color: primaryColor, width: 2), + ), + contentPadding: EdgeInsets.symmetric(horizontal: 14, vertical: 14), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/widgets/wifi_network_card.dart b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/widgets/wifi_network_card.dart new file mode 100644 index 00000000..072e0ff1 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/widgets/wifi_network_card.dart @@ -0,0 +1,85 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:utils/utils.dart'; + +import '../../domain/entities/wifi_network_entity.dart'; + +class WifiNetworkCard extends StatelessWidget { + final WifiNetworkEntity network; + final VoidCallback onDelete; + final ThemePort theme; + + const WifiNetworkCard({ + super.key, + required this.network, + required this.onDelete, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 10, big: 8), + ), + child: Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 16, big: 14), + vertical: SizeUtils.getByScreen(small: 14, big: 12), + ), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundSecondary), + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + child: Row( + children: [ + Icon( + Icons.wifi, + color: theme.getColorFor(ThemeCode.legacyPrimary), + size: SizeUtils.getByScreen(small: 28, big: 30), + ), + SizedBox(width: SizeUtils.getByScreen(small: 12, big: 14)), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + network.ssid, + style: TextStyle( + fontWeight: FontWeight.w600, + color: theme.getColorFor(ThemeCode.textPrimary), + fontSize: SizeUtils.getByScreen(small: 15, big: 16), + ), + ), + SizedBox(height: 2), + Text( + network.bssid, + style: TextStyle( + color: theme.getColorFor(ThemeCode.textPrimary) + .withAlpha(178), + fontSize: SizeUtils.getByScreen(small: 13, big: 14), + ), + ), + ], + ), + ), + InkWell( + onTap: onDelete, + borderRadius: BorderRadius.circular(8), + child: Padding( + padding: EdgeInsets.all( + SizeUtils.getByScreen(small: 6, big: 8), + ), + child: Icon( + Icons.delete_outline, + color: Colors.red, + size: SizeUtils.getByScreen(small: 22, big: 24), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/wifi_settings_screen.dart b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/wifi_settings_screen.dart new file mode 100644 index 00000000..2ba9fe79 --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/wifi_settings/presentation/wifi_settings_screen.dart @@ -0,0 +1,259 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:navigation/navigation.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +import 'state/wifi_settings_view_model.dart'; +import 'widgets/add_wifi_network_sheet.dart'; +import 'widgets/wifi_network_card.dart'; + +class WifiSettingsScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const WifiSettingsScreen({ + super.key, + required this.navigationContract, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final state = ref.watch(wifiSettingsViewModelProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + + ref.listen( + wifiSettingsViewModelProvider.select((s) => s.errorMessage), + (_, errorMessage) { + if (errorMessage.isNotEmpty) { + showTopSnackbar( + context, + message: errorMessage, + type: MessageType.error, + ); + } + }, + ); + + ref.listen( + wifiSettingsViewModelProvider.select((s) => s.successMessage), + (_, successMessage) { + if (successMessage.isNotEmpty) { + showTopSnackbar( + context, + message: context.translate(successMessage), + type: MessageType.success, + ); + ref.read(wifiSettingsViewModelProvider.notifier).clearSuccess(); + } + }, + ); + + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + surfaceTintColor: Colors.transparent, + elevation: 0, + centerTitle: true, + automaticallyImplyLeading: false, + leading: IconButton( + onPressed: () => navigationContract.goBack(), + icon: Icon( + Icons.adaptive.arrow_back, + color: primaryColor, + size: SizeUtils.getByScreen(small: 32, big: 28), + ), + ), + title: Text( + context.translate(I18n.wifiSettings).toUpperCase(), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 19), + fontWeight: FontWeight.w500, + letterSpacing: 0, + color: primaryColor, + ), + ), + actions: [ + Padding( + padding: EdgeInsets.only( + right: SizeUtils.getByScreen(small: 16, big: 14), + ), + child: DecoratedBox( + decoration: BoxDecoration( + color: primaryColor, + shape: BoxShape.circle, + ), + child: IconButton( + onPressed: () => showAddWifiNetworkSheet(context), + icon: Icon( + Icons.add, + color: Colors.white, + size: SizeUtils.getByScreen(small: 24, big: 22), + ), + ), + ), + ), + ], + ), + body: SafeArea( + top: false, + child: state.isLoading + ? const Center(child: CircularProgressIndicator()) + : state.networks.isEmpty + ? _EmptyState(primaryColor: primaryColor) + : _NetworkList(), + ), + ); + } +} + +class _EmptyState extends StatelessWidget { + final Color primaryColor; + + const _EmptyState({required this.primaryColor}); + + @override + Widget build(BuildContext context) { + return Center( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 32, big: 30), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.wifi_off_outlined, + color: primaryColor, + size: SizeUtils.getByScreen(small: 120, big: 140), + ), + SizedBox(height: SizeUtils.getByScreen(small: 20, big: 24)), + Text( + context.translate(I18n.noWifiNetworks), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 16, big: 17), + fontWeight: FontWeight.w500, + color: Colors.grey, + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 10)), + Text( + context.translate(I18n.noWifiNetworksDescription), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 15), + color: Colors.grey, + ), + ), + ], + ), + ), + ); + } +} + +class _NetworkList extends ConsumerWidget { + const _NetworkList(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final networks = ref.watch( + wifiSettingsViewModelProvider.select((s) => s.networks), + ); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + + return SingleChildScrollView( + child: Padding( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), + big: EdgeInsets.symmetric(horizontal: 21, vertical: 8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only( + bottom: SizeUtils.getByScreen(small: 12, big: 10), + ), + child: Text( + context.translate(I18n.wifiDescription), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 14, big: 15), + color: + theme.getColorFor(ThemeCode.textPrimary).withAlpha(178), + ), + ), + ), + ...List.generate(networks.length, (index) { + final network = networks[index]; + return WifiNetworkCard( + network: network, + onDelete: () => + _confirmDelete(context, ref, network), + theme: theme, + ); + }), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), + Text( + context.translate( + I18n.wifiNetworksCount, + args: {'count': networks.length.toString()}, + ), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 14), + color: primaryColor, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ); + } + + void _confirmDelete( + BuildContext context, + WidgetRef ref, + dynamic network, + ) { + final theme = ref.read(themePortProvider); + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(context.translate(I18n.removeWifiNetwork)), + content: Text( + context.translate( + I18n.removeWifiNetworkConfirm, + args: {'name': network.ssid}, + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text( + context.translate(I18n.cancel), + style: TextStyle(color: primaryColor), + ), + ), + TextButton( + onPressed: () { + ref + .read(wifiSettingsViewModelProvider.notifier) + .removeNetwork(network.id); + Navigator.pop(context); + }, + child: Text( + context.translate(I18n.delete), + style: TextStyle(color: Colors.red), + ), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/settings/lib/src/features/wifi_settings/wifi_settings_builder.dart b/modules/legacy/modules/settings/lib/src/features/wifi_settings/wifi_settings_builder.dart new file mode 100644 index 00000000..bb3e017a --- /dev/null +++ b/modules/legacy/modules/settings/lib/src/features/wifi_settings/wifi_settings_builder.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:go_router/go_router.dart'; +import 'package:navigation/navigation.dart'; + +import 'presentation/wifi_settings_screen.dart'; + +class WifiSettingsBuilder { + const WifiSettingsBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = + GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: WifiSettingsScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/settings/melos_settings.iml b/modules/legacy/modules/settings/melos_settings.iml new file mode 100644 index 00000000..9fc8ce79 --- /dev/null +++ b/modules/legacy/modules/settings/melos_settings.iml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/legacy/modules/settings/pubspec.lock b/modules/legacy/modules/settings/pubspec.lock new file mode 100644 index 00000000..a0ca6b44 --- /dev/null +++ b/modules/legacy/modules/settings/pubspec.lock @@ -0,0 +1,1323 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f + url: "https://pub.dev" + source: hosted + version: "85.0.0" + activity: + dependency: "direct overridden" + description: + path: "../../../activity" + relative: true + source: path + version: "0.0.1" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "974859dc0ff5f37bc4313244b3218c791810d03ab3470a579580279ba971a48d" + url: "https://pub.dev" + source: hosted + version: "7.7.1" + archive: + dependency: transitive + description: + name: archive + sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff + url: "https://pub.dev" + source: hosted + version: "4.0.9" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + async: + dependency: transitive + description: + name: async + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" + source: hosted + version: "2.13.0" + auth: + dependency: "direct overridden" + description: + path: "../../../auth" + relative: true + source: path + version: "0.0.1" + 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: ce76b1d48875e3233fde17717c23d1f60a91cc631597e49a400c89b475395b1d + url: "https://pub.dev" + source: hosted + version: "3.1.0" + build_config: + dependency: transitive + description: + name: build_config + sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957 + url: "https://pub.dev" + source: hosted + version: "4.1.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: d1d57f7807debd7349b4726a19fd32ec8bc177c71ad0febf91a20f84cd2d4b46 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: b24597fceb695969d47025c958f3837f9f0122e237c6a22cb082a5ac66c3ca30 + url: "https://pub.dev" + source: hosted + version: "2.7.1" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "066dda7f73d8eb48ba630a55acb50c4a84a2e6b453b1cb4567f581729e794f7b" + url: "https://pub.dev" + source: hosted + version: "9.3.1" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "6ae8a6435a8c6520c7077b107e77f1fb4ba7009633259a4d49a8afd8e7efc5e9" + url: "https://pub.dev" + source: hosted + version: "8.12.4" + 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" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d" + url: "https://pub.dev" + source: hosted + version: "4.11.1" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + confetti: + dependency: transitive + description: + name: confetti + sha256: "979aafde2428c53947892c95eb244466c109c129b7eee9011f0a66caaca52267" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + cookie_jar: + dependency: transitive + description: + name: cookie_jar + sha256: "963da02c1ef64cb5ac20de948c9e5940aa351f1e34a12b1d327c83d85b7e8fff" + url: "https://pub.dev" + source: hosted + version: "4.0.9" + country_code_picker: + dependency: transitive + description: + name: country_code_picker + sha256: f0411f4833b6f98e8b7215f4fa3813bcc88e50f13925f70a170dbd36e3e447f5 + url: "https://pub.dev" + source: hosted + version: "3.4.1" + coverage: + dependency: transitive + description: + name: coverage + sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" + url: "https://pub.dev" + source: hosted + version: "1.15.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + dart_earcut: + dependency: transitive + description: + name: dart_earcut + sha256: e485001bfc05dcbc437d7bfb666316182e3522d4c3f9668048e004d0eb2ce43b + url: "https://pub.dev" + source: hosted + version: "1.2.0" + dart_polylabel2: + dependency: transitive + description: + name: dart_polylabel2 + sha256: "7eeab15ce72894e4bdba6a8765712231fc81be0bd95247de4ad9966abc57adc6" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + design_system: + dependency: "direct main" + description: + path: "../../../../packages/design_system" + relative: true + source: path + version: "0.0.1" + diacritic: + dependency: transitive + description: + name: diacritic + sha256: "12981945ec38931748836cd76f2b38773118d0baef3c68404bdfde9566147876" + url: "https://pub.dev" + source: hosted + version: "0.1.6" + dio: + dependency: "direct main" + description: + name: dio + sha256: aff32c08f92787a557dd5c0145ac91536481831a01b4648136373cddb0e64f8c + url: "https://pub.dev" + source: hosted + version: "5.9.2" + dio_cookie_manager: + dependency: transitive + description: + name: dio_cookie_manager + sha256: "0db1a7b997a0455e488ac35744c68eed3f2a4280d3ab531835a65641b0a08744" + url: "https://pub.dev" + source: hosted + version: "3.4.0" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "2f9e64323a7c3c7ef69567d5c800424a11f8337b8b228bad02524c9fb3c1f340" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + 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" + fl_chart: + dependency: transitive + description: + name: fl_chart + sha256: "7ca9a40f4eb85949190e54087be8b4d6ac09dc4c54238d782a34cf1f7c011de9" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_contacts: + dependency: "direct main" + description: + name: flutter_contacts + sha256: "388d32cd33f16640ee169570128c933b45f3259bddbfae7a100bb49e5ffea9ae" + url: "https://pub.dev" + source: hosted + version: "1.1.9+2" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" + url: "https://pub.dev" + source: hosted + version: "5.0.0" + flutter_map: + dependency: transitive + description: + name: flutter_map + sha256: "391e7dc95cc3f5190748210a69d4cfeb5d8f84dcdfa9c3235d0a9d7742ccb3f8" + url: "https://pub.dev" + source: hosted + version: "8.2.2" + flutter_riverpod: + dependency: "direct main" + description: + name: flutter_riverpod + sha256: "4e166be88e1dbbaa34a280bdb744aeae73b7ef25fdf8db7a3bb776760a3648e2" + url: "https://pub.dev" + source: hosted + version: "3.3.1" + flutter_svg: + dependency: transitive + description: + name: flutter_svg + sha256: "1ded017b39c8e15c8948ea855070a5ff8ff8b3d5e83f3446e02d6bb12add7ad9" + url: "https://pub.dev" + source: hosted + version: "2.2.4" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_treezor_entrust_sdk_bridge: + dependency: "direct overridden" + description: + path: "../../../../packages/flutter_treezor_entrust_sdk_bridge" + relative: true + source: path + version: "1.0.2" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + fonts: + dependency: "direct main" + description: + path: "../../../../packages/fonts" + relative: true + source: path + version: "0.0.1" + freezed: + dependency: "direct main" + description: + name: freezed + sha256: "13065f10e135263a4f5a4391b79a8efc5fb8106f8dd555a9e49b750b45393d77" + url: "https://pub.dev" + source: hosted + version: "3.2.3" + freezed_annotation: + dependency: "direct main" + description: + name: freezed_annotation + sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + get_it: + dependency: "direct main" + description: + name: get_it + sha256: "568d62f0e68666fb5d95519743b3c24a34c7f19d834b0658c46e26d778461f66" + url: "https://pub.dev" + source: hosted + version: "9.2.1" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + go_router: + dependency: "direct main" + description: + name: go_router + sha256: "7974313e217a7771557add6ff2238acb63f635317c35fa590d348fb238f00896" + url: "https://pub.dev" + source: hosted + version: "17.1.0" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + home: + dependency: "direct overridden" + description: + path: "../../../home" + relative: true + source: path + version: "0.0.1" + http: + dependency: transitive + description: + name: http + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" + url: "https://pub.dev" + source: hosted + version: "1.6.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + intl: + dependency: transitive + description: + name: intl + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + url: "https://pub.dev" + source: hosted + version: "0.20.2" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + js: + dependency: transitive + description: + name: js + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + url: "https://pub.dev" + source: hosted + version: "0.7.2" + json_annotation: + dependency: "direct main" + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + json_serializable: + dependency: "direct main" + description: + name: json_serializable + sha256: c5b2ee75210a0f263c6c7b9eeea80553dbae96ea1bf57f02484e806a3ffdffa3 + url: "https://pub.dev" + source: hosted + version: "6.11.2" + l10n_countries: + dependency: transitive + description: + name: l10n_countries + sha256: dfeb4d4925f71d61d2c495a0f0e1430fe66ce664cf87533dd10dc445cab0ff02 + url: "https://pub.dev" + source: hosted + version: "1.3.1" + l10n_currencies: + dependency: transitive + description: + name: l10n_currencies + sha256: "7a64e1e2ae7e8aae00cca3d079f7bef333f255bff98976ddf765121e2e5eb87e" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + l10n_languages: + dependency: transitive + description: + name: l10n_languages + sha256: "808f25db80df1697f9e8f05cdc9f2dad11a21ea6473f14f7bb65bef7082b27d3" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + latlong2: + dependency: transitive + description: + name: latlong2 + sha256: "98227922caf49e6056f91b6c56945ea1c7b166f28ffcd5fb8e72fc0b453cc8fe" + url: "https://pub.dev" + source: hosted + version: "0.9.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" + legacy_shared: + dependency: "direct main" + description: + path: "../../packages/legacy_shared" + relative: true + source: path + version: "0.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 + url: "https://pub.dev" + source: hosted + version: "5.1.1" + lists: + dependency: transitive + description: + name: lists + sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + logger: + dependency: transitive + description: + name: logger + sha256: a7967e31b703831a893bbc3c3dd11db08126fe5f369b5c648a36f821979f5be3 + url: "https://pub.dev" + source: hosted + version: "2.6.2" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + lottie: + dependency: transitive + description: + name: lottie + sha256: "8ae0be46dbd9e19641791dc12ee480d34e1fd3f84c749adc05f3ad9342b71b95" + url: "https://pub.dev" + source: hosted + version: "3.3.2" + 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: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + url: "https://pub.dev" + source: hosted + version: "1.16.0" + mgrs_dart: + dependency: transitive + description: + name: mgrs_dart + sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mobile_scanner: + dependency: transitive + description: + name: mobile_scanner + sha256: c92c26bf2231695b6d3477c8dcf435f51e28f87b1745966b1fe4c47a286171ce + url: "https://pub.dev" + source: hosted + version: "7.2.0" + navigation: + dependency: "direct main" + description: + path: "../../../../packages/navigation" + relative: true + source: path + version: "0.0.1" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + notifications: + dependency: "direct overridden" + description: + path: "../../../notifications" + relative: true + source: path + version: "0.0.1" + 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: transitive + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + 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: "6d13aece7b3f5c5a9731eaf553ff9dcbc2eff41087fd2df587fd0fed9a3eb0c4" + url: "https://pub.dev" + source: hosted + version: "2.5.1" + 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" + payments: + dependency: "direct overridden" + description: + path: "../../../../packages/payments" + relative: true + source: path + version: "0.0.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" + url: "https://pub.dev" + source: hosted + version: "7.0.2" + 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" + pool: + dependency: transitive + description: + name: pool + sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" + url: "https://pub.dev" + source: hosted + version: "1.5.2" + posix: + dependency: transitive + description: + name: posix + sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07" + url: "https://pub.dev" + source: hosted + version: "6.5.0" + proj4dart: + dependency: transitive + description: + name: proj4dart + sha256: c8a659ac9b6864aa47c171e78d41bbe6f5e1d7bd790a5814249e6b68bc44324e + url: "https://pub.dev" + source: hosted + version: "2.1.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + riverpod: + dependency: transitive + description: + name: riverpod + sha256: "8c22216be8ad3ef2b44af3a329693558c98eca7b8bd4ef495c92db0bba279f83" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + sca_treezor: + dependency: "direct overridden" + description: + path: "../../../../packages/sca_treezor" + relative: true + source: path + version: "0.0.1" + sealed_countries: + dependency: transitive + description: + name: sealed_countries + sha256: bfb57edd964ca553da380ef181f665307b2847db418144b5d896a03e1adb06cc + url: "https://pub.dev" + source: hosted + version: "2.8.0" + sealed_currencies: + dependency: transitive + description: + name: sealed_currencies + sha256: "5885c77381cca83348529afd25d2ae7c0da295e972a6310c1acd1a8ae0033734" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + sealed_languages: + dependency: transitive + description: + name: sealed_languages + sha256: "488a2bc6ccf01bbc0182b8c3203af9cc1a85dc1c6aa3d39792539643d11d199c" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + sf_infrastructure: + dependency: "direct main" + description: + path: "../../../../packages/sf_infrastructure" + relative: true + source: path + version: "0.0.1" + sf_localizations: + dependency: "direct main" + description: + path: "../../../../packages/sf_localizations" + relative: true + source: path + version: "0.0.1" + sf_shared: + dependency: "direct main" + description: + path: "../../../../packages/sf_shared" + relative: true + source: path + version: "0.0.1" + shared_preferences: + dependency: transitive + description: + name: shared_preferences + sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "8374d6200ab33ac99031a852eba4c8eb2170c4bf20778b3e2c9eccb45384fb41" + url: "https://pub.dev" + source: hosted + version: "2.4.21" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" + url: "https://pub.dev" + source: hosted + version: "2.5.6" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + url: "https://pub.dev" + source: hosted + version: "2.4.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "800f12fb87434defa13432ab37e33051b43b290a174e15259563b043cda40c46" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "6a3c6cc82073a8797f8c4dc4572146114a39652851c157db37e964d9c7038723" + url: "https://pub.dev" + source: hosted + version: "1.3.8" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" + 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" + state_notifier: + dependency: transitive + description: + name: state_notifier + sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb + url: "https://pub.dev" + source: hosted + version: "1.0.0" + 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" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test: + dependency: transitive + description: + name: test + sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb" + url: "https://pub.dev" + source: hosted + version: "1.26.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" + url: "https://pub.dev" + source: hosted + version: "0.7.6" + test_core: + dependency: transitive + description: + name: test_core + sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a" + url: "https://pub.dev" + source: hosted + version: "0.6.11" + timing: + dependency: transitive + description: + name: timing + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + top_snackbar_flutter: + dependency: transitive + description: + name: top_snackbar_flutter + sha256: ad3f93062450e8c7db97b271d405c180536408cc2be4380a59da7022eb1d750c + url: "https://pub.dev" + source: hosted + version: "3.3.0" + 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" + universal_io: + dependency: transitive + description: + name: universal_io + sha256: f63cbc48103236abf48e345e07a03ce5757ea86285ed313a6a032596ed9301e2 + url: "https://pub.dev" + source: hosted + version: "2.3.1" + utils: + dependency: "direct main" + description: + path: "../../../../packages/utils" + relative: true + source: path + version: "0.0.1" + uuid: + dependency: "direct main" + description: + name: uuid + sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" + url: "https://pub.dev" + source: hosted + version: "4.5.3" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "7076216a10d5c390315fbe536a30f1254c341e7543e6c4c8a815e591307772b1" + url: "https://pub.dev" + source: hosted + version: "1.1.20" + 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: "5a88dd14c0954a5398af544651c7fb51b457a2a556949bfb25369b210ef73a74" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" + 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" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + webview_flutter: + dependency: transitive + description: + name: webview_flutter + sha256: a3da219916aba44947d3a5478b1927876a09781174b5a2b67fa5be0555154bf9 + url: "https://pub.dev" + source: hosted + version: "4.13.1" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: "2a03df01df2fd30b075d1e7f24c28aee593f2e5d5ac4c3c4283c5eda63717b24" + url: "https://pub.dev" + source: hosted + version: "4.10.13" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: "63d26ee3aca7256a83ccb576a50272edd7cfc80573a4305caa98985feb493ee0" + url: "https://pub.dev" + source: hosted + version: "2.14.0" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: "2df8fd9ada04d699b9db8e79aa783a16e5d89b69e5b74009b87e16b59912cf98" + url: "https://pub.dev" + source: hosted + version: "3.24.0" + wkt_parser: + dependency: transitive + description: + name: wkt_parser + sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + 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.9.2 <4.0.0" + flutter: ">=3.35.0" diff --git a/modules/legacy/modules/settings/pubspec.yaml b/modules/legacy/modules/settings/pubspec.yaml new file mode 100644 index 00000000..16e467dd --- /dev/null +++ b/modules/legacy/modules/settings/pubspec.yaml @@ -0,0 +1,54 @@ +name: settings +description: "Settings module for legacy device management features." + +version: 1.0.0+1 + +environment: + sdk: ^3.9.2 + +dependencies: + flutter: + sdk: flutter + #packages dependencies go here + design_system: + path: ../../../../packages/design_system + navigation: + path: ../../../../packages/navigation + sf_localizations: + path: ../../../../packages/sf_localizations + sf_infrastructure: + path: ../../../../packages/sf_infrastructure + utils: + path: ../../../../packages/utils + fonts: + path: ../../../../packages/fonts + legacy_shared: + path: ../../packages/legacy_shared + sf_shared: + path: ../../../../packages/sf_shared + #dependencies go here + get_it: ^9.0.5 + go_router: ^17.0.0 + flutter_riverpod: ^3.0.3 + freezed_annotation: ^3.1.0 + freezed: ^3.2.3 + json_annotation: ^4.9.0 + json_serializable: ^6.11.2 + cupertino_icons: ^1.0.8 + dio: ^5.8.0+1 + uuid: ^4.5.1 + flutter_contacts: ^1.1.9+2 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + build_runner: ^2.4.15 + +flutter: + uses-material-design: true + + module: + androidX: true + androidPackage: com.example.settings + iosBundleIdentifier: com.example.settings diff --git a/modules/legacy/modules/settings/pubspec_overrides.yaml b/modules/legacy/modules/settings/pubspec_overrides.yaml new file mode 100644 index 00000000..d10e1fe1 --- /dev/null +++ b/modules/legacy/modules/settings/pubspec_overrides.yaml @@ -0,0 +1,32 @@ +# melos_managed_dependency_overrides: activity,auth,design_system,flutter_treezor_entrust_sdk_bridge,fonts,home,legacy_shared,navigation,notifications,payments,sca_treezor,sf_infrastructure,sf_localizations,sf_shared,utils +dependency_overrides: + activity: + path: ../../../activity + auth: + path: ../../../auth + design_system: + path: ../../../../packages/design_system + flutter_treezor_entrust_sdk_bridge: + path: ../../../../packages/flutter_treezor_entrust_sdk_bridge + fonts: + path: ../../../../packages/fonts + home: + path: ../../../home + legacy_shared: + path: ../../packages/legacy_shared + navigation: + path: ../../../../packages/navigation + notifications: + path: ../../../notifications + payments: + path: ../../../../packages/payments + sca_treezor: + path: ../../../../packages/sca_treezor + sf_infrastructure: + path: ../../../../packages/sf_infrastructure + sf_localizations: + path: ../../../../packages/sf_localizations + sf_shared: + path: ../../../../packages/sf_shared + utils: + path: ../../../../packages/utils diff --git a/modules/legacy/packages/legacy_shared/lib/legacy_shared.dart b/modules/legacy/packages/legacy_shared/lib/legacy_shared.dart index 8f42bd38..eb8b86ce 100644 --- a/modules/legacy/packages/legacy_shared/lib/legacy_shared.dart +++ b/modules/legacy/packages/legacy_shared/lib/legacy_shared.dart @@ -3,6 +3,7 @@ library legacy_shared; export 'src/providers/selected_device_provider.dart'; export 'src/widgets/layouts/page_layout.dart'; export 'src/components/section_button.dart'; +export 'src/widgets/week_day_chips.dart'; export 'src/components/menu_button.dart'; export 'src/data/models/device_response_model.dart'; export 'src/data/models/get_devices_response_model.dart'; diff --git a/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.dart b/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.dart index 556211ad..3f0760f0 100644 --- a/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.dart +++ b/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.dart @@ -3,14 +3,23 @@ import 'package:freezed_annotation/freezed_annotation.dart'; part 'send_command_request_model.freezed.dart'; part 'send_command_request_model.g.dart'; +enum DeviceCommand { + @JsonValue('FIND_DEVICE') + findDevice, + @JsonValue('REWARDS') + rewards, + @JsonValue('SOUND') + sound, +} + @freezed abstract class SendCommandRequestModel with _$SendCommandRequestModel { const factory SendCommandRequestModel({ required String device, - required String command, + required DeviceCommand command, Map? data, }) = _SendCommandRequestModel; factory SendCommandRequestModel.fromJson(Map json) => _$SendCommandRequestModelFromJson(json); -} \ No newline at end of file +} diff --git a/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.freezed.dart b/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.freezed.dart index 72f5a14b..29f1116b 100644 --- a/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.freezed.dart +++ b/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.freezed.dart @@ -15,7 +15,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$SendCommandRequestModel { - String get device; String get command; Map? get data; + String get device; DeviceCommand get command; Map? get data; /// Create a copy of SendCommandRequestModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -48,7 +48,7 @@ abstract mixin class $SendCommandRequestModelCopyWith<$Res> { factory $SendCommandRequestModelCopyWith(SendCommandRequestModel value, $Res Function(SendCommandRequestModel) _then) = _$SendCommandRequestModelCopyWithImpl; @useResult $Res call({ - String device, String command, Map? data + String device, DeviceCommand command, Map? data }); @@ -69,7 +69,7 @@ class _$SendCommandRequestModelCopyWithImpl<$Res> return _then(_self.copyWith( device: null == device ? _self.device : device // ignore: cast_nullable_to_non_nullable as String,command: null == command ? _self.command : command // ignore: cast_nullable_to_non_nullable -as String,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable +as DeviceCommand,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable as Map?, )); } @@ -155,7 +155,7 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String device, String command, Map? data)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String device, DeviceCommand command, Map? data)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _SendCommandRequestModel() when $default != null: return $default(_that.device,_that.command,_that.data);case _: @@ -176,7 +176,7 @@ return $default(_that.device,_that.command,_that.data);case _: /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String device, String command, Map? data) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String device, DeviceCommand command, Map? data) $default,) {final _that = this; switch (_that) { case _SendCommandRequestModel(): return $default(_that.device,_that.command,_that.data);case _: @@ -196,7 +196,7 @@ return $default(_that.device,_that.command,_that.data);case _: /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String device, String command, Map? data)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String device, DeviceCommand command, Map? data)? $default,) {final _that = this; switch (_that) { case _SendCommandRequestModel() when $default != null: return $default(_that.device,_that.command,_that.data);case _: @@ -215,7 +215,7 @@ class _SendCommandRequestModel implements SendCommandRequestModel { factory _SendCommandRequestModel.fromJson(Map json) => _$SendCommandRequestModelFromJson(json); @override final String device; -@override final String command; +@override final DeviceCommand command; final Map? _data; @override Map? get data { final value = _data; @@ -259,7 +259,7 @@ abstract mixin class _$SendCommandRequestModelCopyWith<$Res> implements $SendCom factory _$SendCommandRequestModelCopyWith(_SendCommandRequestModel value, $Res Function(_SendCommandRequestModel) _then) = __$SendCommandRequestModelCopyWithImpl; @override @useResult $Res call({ - String device, String command, Map? data + String device, DeviceCommand command, Map? data }); @@ -280,7 +280,7 @@ class __$SendCommandRequestModelCopyWithImpl<$Res> return _then(_SendCommandRequestModel( device: null == device ? _self.device : device // ignore: cast_nullable_to_non_nullable as String,command: null == command ? _self.command : command // ignore: cast_nullable_to_non_nullable -as String,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable +as DeviceCommand,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable as Map?, )); } diff --git a/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.g.dart b/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.g.dart index b40aae06..1b16e1c7 100644 --- a/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.g.dart +++ b/modules/legacy/packages/legacy_shared/lib/src/data/models/send_command_request_model.g.dart @@ -10,7 +10,7 @@ _SendCommandRequestModel _$SendCommandRequestModelFromJson( Map json, ) => _SendCommandRequestModel( device: json['device'] as String, - command: json['command'] as String, + command: $enumDecode(_$DeviceCommandEnumMap, json['command']), data: json['data'] as Map?, ); @@ -18,6 +18,12 @@ Map _$SendCommandRequestModelToJson( _SendCommandRequestModel instance, ) => { 'device': instance.device, - 'command': instance.command, + 'command': _$DeviceCommandEnumMap[instance.command]!, 'data': instance.data, }; + +const _$DeviceCommandEnumMap = { + DeviceCommand.findDevice: 'FIND_DEVICE', + DeviceCommand.rewards: 'REWARDS', + DeviceCommand.sound: 'SOUND', +}; diff --git a/modules/legacy/packages/legacy_shared/lib/src/widgets/layouts/page_layout.dart b/modules/legacy/packages/legacy_shared/lib/src/widgets/layouts/page_layout.dart index 11e9c942..905562e8 100644 --- a/modules/legacy/packages/legacy_shared/lib/src/widgets/layouts/page_layout.dart +++ b/modules/legacy/packages/legacy_shared/lib/src/widgets/layouts/page_layout.dart @@ -4,11 +4,11 @@ import 'package:get_it/get_it.dart'; import 'package:navigation/navigation.dart'; import 'package:utils/utils.dart'; -class LegacyPageLayout extends StatelessWidget{ - +class LegacyPageLayout extends StatelessWidget { final String title; final Widget body; final Widget? footer; + final bool showBack; final bool showEdit; final VoidCallback? onEditChange; final ThemePort theme; @@ -18,6 +18,7 @@ class LegacyPageLayout extends StatelessWidget{ required this.title, required this.body, this.footer, + this.showBack = true, this.showEdit = false, this.onEditChange, required this.theme, @@ -27,66 +28,63 @@ class LegacyPageLayout extends StatelessWidget{ Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, - body: SafeArea( - child: Column( - children: [ - Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.fromLTRB(22, 20, 22, 0), - big: EdgeInsets.fromLTRB(21, 16, 21, 0), + appBar: AppBar( + backgroundColor: Colors.white, + surfaceTintColor: Colors.transparent, + elevation: 0, + centerTitle: true, + automaticallyImplyLeading: false, + leading: showBack + ? IconButton( + onPressed: () => GetIt.I().goBack(), + icon: Icon( + Icons.adaptive.arrow_back, + color: theme.getColorFor(ThemeCode.legacyPrimary), + size: SizeUtils.getByScreen(small: 32, big: 28), + ), + ) + : null, + title: Text( + title.toUpperCase(), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 19), + fontWeight: FontWeight.w500, + letterSpacing: 0, + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), + ), + actions: [ + if (showEdit) + Padding( + padding: EdgeInsets.only( + right: SizeUtils.getByScreen(small: 16, big: 14), ), - child: Stack( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - IconButton(onPressed: () { - GetIt.I().goBack(); - }, - icon: Icon(Icons.arrow_back, - color: theme.getColorFor(ThemeCode.legacyPrimary), - size: 32, - ), - padding: EdgeInsets.zero, - ), - if (showEdit) - DecoratedBox( - decoration: BoxDecoration( - color: theme.getColorFor(ThemeCode.legacyPrimary), - shape: BoxShape.circle - ), - child: IconButton(onPressed: onEditChange, - icon: Icon(Icons.edit_outlined, - color: Colors.white, - size: SizeUtils.getByScreen(small: 30, big: 28), - ) - ), - ) - ], + child: DecoratedBox( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.legacyPrimary), + shape: BoxShape.circle, + ), + child: IconButton( + onPressed: onEditChange, + icon: Icon( + Icons.edit_outlined, + color: Colors.white, + size: SizeUtils.getByScreen(small: 24, big: 22), ), - SizedBox( - height: 50, - child: Center( - child: Text(title.toUpperCase(), - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 20, big: 19), - fontWeight: FontWeight.w500, - letterSpacing: 0, - color: theme.getColorFor(ThemeCode.legacyPrimary) - ), - ) - ) - ) - ], + ), ), ), - SizedBox(height: SizeUtils.getByScreen(small: 30, big: 28)), + ], + ), + body: SafeArea( + top: false, + child: Column( + children: [ Expanded(child: body), - ?footer + ?footer, ], - ) + ), ), ); } - -} \ No newline at end of file +} diff --git a/modules/legacy/packages/legacy_shared/lib/src/widgets/week_day_chips.dart b/modules/legacy/packages/legacy_shared/lib/src/widgets/week_day_chips.dart new file mode 100644 index 00000000..8f0616eb --- /dev/null +++ b/modules/legacy/packages/legacy_shared/lib/src/widgets/week_day_chips.dart @@ -0,0 +1,135 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/widgets.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +const weekDayI18nKeys = { + 1: I18n.monday, + 2: I18n.tuesday, + 3: I18n.wednesday, + 4: I18n.thursday, + 5: I18n.friday, + 6: I18n.saturday, + 7: I18n.sunday, +}; + +String weekDayShortLabel(BuildContext context, String i18nKey) { + final fullName = context.translate(i18nKey); + return fullName.length > 3 ? fullName.substring(0, 3) : fullName; +} + +/// Shared weekday chip selector that supports both single and multi-select. +/// +/// **Single select** (for scheduled activities): +/// ```dart +/// WeekDayChips.single( +/// selectedWeekDay: 1, +/// onChanged: (day) => ..., +/// theme: theme, +/// ) +/// ``` +/// +/// **Multi select** (for alarms): +/// ```dart +/// WeekDayChips.multi( +/// selectedDays: [true, false, true, ...], +/// onToggle: (index) => ..., +/// theme: theme, +/// ) +/// ``` +class WeekDayChips extends StatelessWidget { + /// Single-select mode: which day is selected (1=Mon, 7=Sun). + final int? selectedWeekDay; + + /// Single-select callback. + final ValueChanged? onChanged; + + /// Multi-select mode: 7 booleans (index 0=Mon, 6=Sun). + final List? selectedDays; + + /// Multi-select callback with day index (0-6). + final ValueChanged? onToggle; + + final bool enabled; + final ThemePort theme; + + const WeekDayChips.single({ + super.key, + required int this.selectedWeekDay, + required ValueChanged this.onChanged, + required this.theme, + this.enabled = true, + }) : selectedDays = null, + onToggle = null; + + const WeekDayChips.multi({ + super.key, + required List this.selectedDays, + required ValueChanged this.onToggle, + required this.theme, + this.enabled = true, + }) : selectedWeekDay = null, + onChanged = null; + + bool _isMulti() => selectedDays != null; + + @override + Widget build(BuildContext context) { + final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary); + + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: weekDayI18nKeys.entries.map((e) { + final dayIndex = e.key - 1; // 0-based + final isSelected = _isMulti() + ? selectedDays![dayIndex] + : e.key == selectedWeekDay; + final label = weekDayShortLabel(context, e.value); + + return GestureDetector( + onTap: enabled + ? () { + if (_isMulti()) { + onToggle!(dayIndex); + } else { + onChanged!(e.key); + } + } + : null, + child: Container( + width: SizeUtils.getByScreen(small: 42, big: 40), + height: SizeUtils.getByScreen(small: 38, big: 36), + alignment: Alignment.center, + decoration: BoxDecoration( + color: isSelected ? primaryColor : const Color(0x00000000), + borderRadius: BorderRadius.circular( + SizeUtils.getByScreen(small: 8, big: 7), + ), + border: Border.all( + color: isSelected + ? primaryColor + : enabled + ? const Color(0xFFBDBDBD) + : const Color(0xFFE0E0E0), + ), + ), + child: Text( + label, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 13, big: 12), + fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, + color: isSelected + ? const Color(0xFFFFFFFF) + : enabled + ? theme.getColorFor(ThemeCode.textPrimary) + : theme + .getColorFor(ThemeCode.textPrimary) + .withValues(alpha: 0.4), + ), + ), + ), + ); + }).toList(), + ); + } +} diff --git a/modules/profile/devtools_options.yaml b/modules/profile/devtools_options.yaml new file mode 100644 index 00000000..fa0b357c --- /dev/null +++ b/modules/profile/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/modules/splash/devtools_options.yaml b/modules/splash/devtools_options.yaml new file mode 100644 index 00000000..fa0b357c --- /dev/null +++ b/modules/splash/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/packages/design_system/lib/src/dropdowns/dropdown.dart b/packages/design_system/lib/src/dropdowns/dropdown.dart index 97ee4749..88e86f89 100644 --- a/packages/design_system/lib/src/dropdowns/dropdown.dart +++ b/packages/design_system/lib/src/dropdowns/dropdown.dart @@ -57,6 +57,7 @@ class CustomDropdown extends StatelessWidget { height: height, child: Center( child: DropdownButtonFormField( + isExpanded: true, icon: showIcon ? null : const SizedBox.shrink(), dropdownColor: Colors.white, decoration: InputDecoration( diff --git a/packages/flutter_treezor_entrust_sdk_bridge/.dart_tool/package_config.json b/packages/flutter_treezor_entrust_sdk_bridge/.dart_tool/package_config.json index 86a0d483..b48375e6 100644 --- a/packages/flutter_treezor_entrust_sdk_bridge/.dart_tool/package_config.json +++ b/packages/flutter_treezor_entrust_sdk_bridge/.dart_tool/package_config.json @@ -3,163 +3,163 @@ "packages": [ { "name": "async", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.11.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/async-2.11.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "boolean_selector", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/boolean_selector-2.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "characters", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/characters-1.4.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/characters-1.4.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "clock", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/clock-1.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/clock-1.1.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "collection", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/collection-1.19.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "fake_async", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/fake_async-1.3.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "flutter", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "flutter_lints", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_lints-4.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_lints-4.0.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "flutter_test", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter_test", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter_test", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "leak_tracker", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker-11.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/leak_tracker-11.0.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "leak_tracker_flutter_testing", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.10", + "rootUri": "file:///Users/juliandalcalaf/.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/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_testing-3.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "lints", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/lints-4.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/lints-4.0.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "matcher", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/matcher-0.12.17", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/matcher-0.12.17", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "material_color_utilities", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/material_color_utilities-0.11.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "meta", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.16.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/meta-1.16.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "path", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path-1.9.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "plugin_platform_interface", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/plugin_platform_interface-2.1.8", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "sky_engine", - "rootUri": "file:///C:/Program%20Files/Flutter/bin/cache/pkg/sky_engine", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/bin/cache/pkg/sky_engine", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "source_span", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_span-1.10.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "stack_trace", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stack_trace-1.12.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "stream_channel", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stream_channel-2.1.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stream_channel-2.1.4", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "string_scanner", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/string_scanner-1.3.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "term_glyph", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/term_glyph-1.2.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "test_api", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/test_api-0.7.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/test_api-0.7.6", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "vector_math", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_math-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_math-2.2.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "vm_service", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vm_service-14.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vm_service-14.3.0", "packageUri": "lib/", "languageVersion": "3.3" }, @@ -172,7 +172,7 @@ ], "generator": "pub", "generatorVersion": "3.9.2", - "flutterRoot": "file:///C:/Program%20Files/Flutter", - "flutterVersion": "3.35.6", - "pubCache": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache" + "flutterRoot": "file:///Users/juliandalcalaf/Development/flutter", + "flutterVersion": "3.35.7", + "pubCache": "file:///Users/juliandalcalaf/.pub-cache" } diff --git a/packages/flutter_treezor_entrust_sdk_bridge/.dart_tool/version b/packages/flutter_treezor_entrust_sdk_bridge/.dart_tool/version index eb4861ac..e119acda 100644 --- a/packages/flutter_treezor_entrust_sdk_bridge/.dart_tool/version +++ b/packages/flutter_treezor_entrust_sdk_bridge/.dart_tool/version @@ -1 +1 @@ -3.35.6 \ No newline at end of file +3.35.7 \ No newline at end of file diff --git a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml index 19b5e889..28301667 100644 --- a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml +++ b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml @@ -7,6 +7,6 @@ 2.6.4 - 20260312000000 + 20260316000000 diff --git a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.md5 b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.md5 index 63a77637..9d12d556 100644 --- a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.md5 +++ b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.md5 @@ -1 +1 @@ -a9c8c5ab69327988cd562b4a81d75996 \ No newline at end of file +a0ed8b315dd3aaa92839422686f00f9d \ No newline at end of file diff --git a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.sha1 b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.sha1 index b6a39a94..a2a39a3d 100644 --- a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.sha1 +++ b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.sha1 @@ -1 +1 @@ -c9283cd399a3a0f0957dd630a31b744fd45b9fd6 \ No newline at end of file +4888c373e3701bd965ce8ff0daaa19071f7d9a9e \ No newline at end of file diff --git a/packages/flutter_treezor_entrust_sdk_bridge/example/.dart_tool/package_config.json b/packages/flutter_treezor_entrust_sdk_bridge/example/.dart_tool/package_config.json index 169c6e02..2ae76611 100644 --- a/packages/flutter_treezor_entrust_sdk_bridge/example/.dart_tool/package_config.json +++ b/packages/flutter_treezor_entrust_sdk_bridge/example/.dart_tool/package_config.json @@ -3,91 +3,91 @@ "packages": [ { "name": "async", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.11.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/async-2.11.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "boolean_selector", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/boolean_selector-2.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "characters", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/characters-1.4.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/characters-1.4.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "clock", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/clock-1.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/clock-1.1.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "collection", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/collection-1.19.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "crypto", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/crypto-3.0.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/crypto-3.0.6", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "cupertino_icons", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cupertino_icons-1.0.8", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "dio", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dio-5.7.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dio-5.7.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "dio_web_adapter", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dio_web_adapter-2.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dio_web_adapter-2.0.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "fake_async", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/fake_async-1.3.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "file", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/file-7.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/file-7.0.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "flutter", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "flutter_driver", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter_driver", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter_driver", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "flutter_lints", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_lints-4.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_lints-4.0.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "flutter_test", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter_test", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter_test", "packageUri": "lib/", "languageVersion": "3.8" }, @@ -99,163 +99,163 @@ }, { "name": "fuchsia_remote_debug_protocol", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/fuchsia_remote_debug_protocol", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/fuchsia_remote_debug_protocol", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "http_parser", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http_parser-4.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http_parser-4.0.2", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "integration_test", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/integration_test", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/integration_test", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "leak_tracker", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker-11.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/leak_tracker-11.0.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "leak_tracker_flutter_testing", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.10", + "rootUri": "file:///Users/juliandalcalaf/.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/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_testing-3.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "lints", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/lints-4.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/lints-4.0.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "matcher", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/matcher-0.12.17", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/matcher-0.12.17", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "material_color_utilities", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/material_color_utilities-0.11.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "meta", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.16.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/meta-1.16.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "path", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path-1.9.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "platform", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/platform-3.1.5", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/platform-3.1.5", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "plugin_platform_interface", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/plugin_platform_interface-2.1.8", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "process", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/process-5.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/process-5.0.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "sky_engine", - "rootUri": "file:///C:/Program%20Files/Flutter/bin/cache/pkg/sky_engine", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/bin/cache/pkg/sky_engine", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "source_span", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_span-1.10.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "stack_trace", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stack_trace-1.12.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "stream_channel", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stream_channel-2.1.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stream_channel-2.1.4", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "string_scanner", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/string_scanner-1.3.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "sync_http", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/sync_http-0.3.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/sync_http-0.3.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "term_glyph", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/term_glyph-1.2.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "test_api", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/test_api-0.7.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/test_api-0.7.6", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "typed_data", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/typed_data-1.4.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/typed_data-1.4.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "vector_math", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_math-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_math-2.2.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "vm_service", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vm_service-14.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vm_service-14.3.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "web", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web-1.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web-1.1.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "webdriver", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/webdriver-3.0.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/webdriver-3.0.4", "packageUri": "lib/", "languageVersion": "3.1" }, @@ -268,7 +268,7 @@ ], "generator": "pub", "generatorVersion": "3.9.2", - "flutterRoot": "file:///C:/Program%20Files/Flutter", - "flutterVersion": "3.35.6", - "pubCache": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache" + "flutterRoot": "file:///Users/juliandalcalaf/Development/flutter", + "flutterVersion": "3.35.7", + "pubCache": "file:///Users/juliandalcalaf/.pub-cache" } diff --git a/packages/flutter_treezor_entrust_sdk_bridge/example/.flutter-plugins-dependencies b/packages/flutter_treezor_entrust_sdk_bridge/example/.flutter-plugins-dependencies index cb9bd6c5..471e06ef 100644 --- a/packages/flutter_treezor_entrust_sdk_bridge/example/.flutter-plugins-dependencies +++ b/packages/flutter_treezor_entrust_sdk_bridge/example/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"C:\\\\dev\\\\sf-app-platform\\\\packages\\\\flutter_treezor_entrust_sdk_bridge\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"integration_test","path":"C:\\\\Program Files\\\\Flutter\\\\packages\\\\integration_test\\\\","native_build":true,"dependencies":[],"dev_dependency":true}],"android":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"C:\\\\dev\\\\sf-app-platform\\\\packages\\\\flutter_treezor_entrust_sdk_bridge\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"integration_test","path":"C:\\\\Program Files\\\\Flutter\\\\packages\\\\integration_test\\\\","native_build":true,"dependencies":[],"dev_dependency":true}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_treezor_entrust_sdk_bridge","dependencies":[]},{"name":"integration_test","dependencies":[]}],"date_created":"2026-03-09 10:56:54.692811","version":"3.35.6","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"/Users/juliandalcalaf/Desktop/apps/sf-app-platform/packages/flutter_treezor_entrust_sdk_bridge/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"integration_test","path":"/Users/juliandalcalaf/Development/flutter/packages/integration_test/","native_build":true,"dependencies":[],"dev_dependency":true}],"android":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"/Users/juliandalcalaf/Desktop/apps/sf-app-platform/packages/flutter_treezor_entrust_sdk_bridge/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"integration_test","path":"/Users/juliandalcalaf/Development/flutter/packages/integration_test/","native_build":true,"dependencies":[],"dev_dependency":true}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_treezor_entrust_sdk_bridge","dependencies":[]},{"name":"integration_test","dependencies":[]}],"date_created":"2026-03-13 09:49:17.301395","version":"3.35.7","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file diff --git a/packages/flutter_treezor_entrust_sdk_bridge/example/android/local.properties b/packages/flutter_treezor_entrust_sdk_bridge/example/android/local.properties index 3a59a23e..608a06d2 100644 --- a/packages/flutter_treezor_entrust_sdk_bridge/example/android/local.properties +++ b/packages/flutter_treezor_entrust_sdk_bridge/example/android/local.properties @@ -1,3 +1,3 @@ -sdk.dir=C:\\dev\\sdk\\android -flutter.sdk=C:\\Program Files\\Flutter +sdk.dir=/Users/juliandalcalaf/Library/Android/sdk +flutter.sdk=/Users/juliandalcalaf/Development/flutter flutter.buildMode=debug \ No newline at end of file diff --git a/packages/fonts/.dart_tool/package_config.json b/packages/fonts/.dart_tool/package_config.json index 8f2356e6..a9903353 100644 --- a/packages/fonts/.dart_tool/package_config.json +++ b/packages/fonts/.dart_tool/package_config.json @@ -3,43 +3,43 @@ "packages": [ { "name": "characters", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/characters-1.4.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/characters-1.4.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "collection", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/collection-1.19.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "flutter", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "material_color_utilities", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/material_color_utilities-0.11.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "meta", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.16.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/meta-1.16.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "sky_engine", - "rootUri": "file:///C:/Program%20Files/Flutter/bin/cache/pkg/sky_engine", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/bin/cache/pkg/sky_engine", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "vector_math", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_math-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_math-2.2.0", "packageUri": "lib/", "languageVersion": "3.1" }, @@ -52,7 +52,7 @@ ], "generator": "pub", "generatorVersion": "3.9.2", - "flutterRoot": "file:///C:/Program%20Files/Flutter", - "flutterVersion": "3.35.6", - "pubCache": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache" + "flutterRoot": "file:///Users/juliandalcalaf/Development/flutter", + "flutterVersion": "3.35.7", + "pubCache": "file:///Users/juliandalcalaf/.pub-cache" } diff --git a/packages/fonts/.dart_tool/version b/packages/fonts/.dart_tool/version index eb4861ac..e119acda 100644 --- a/packages/fonts/.dart_tool/version +++ b/packages/fonts/.dart_tool/version @@ -1 +1 @@ -3.35.6 \ No newline at end of file +3.35.7 \ No newline at end of file diff --git a/packages/navigation/lib/app_routes.dart b/packages/navigation/lib/app_routes.dart index 166e5084..e68a2aea 100644 --- a/packages/navigation/lib/app_routes.dart +++ b/packages/navigation/lib/app_routes.dart @@ -47,10 +47,18 @@ class AppRoutes { static const deviceManagement = '$legacyDashboard/device_management'; static const legacyLocation = '$legacyDashboard/location'; + static const scheduledActivities = '$deviceManagement/scheduled_activities'; static const contacts = '$deviceManagement/contacts'; + static const editContact = '$contacts/edit/:contactId'; + + static String editContactPath(String contactId) => + '$contacts/edit/$contactId'; + static const health = '$deviceManagement/health'; static const remoteConnection = '$deviceManagement/remote_connection'; static const locateDevice = '$deviceManagement/locate_device'; static const rewards = '$deviceManagement/rewards'; + static const activityMeter = '$deviceManagement/activity_meter'; + static const appsUse = '$deviceManagement/apps_use'; static const legacyLogin = '$legacy/login'; static const legacySignup = '$legacy/signup'; diff --git a/packages/payments/.dart_tool/extension_discovery/devtools.json b/packages/payments/.dart_tool/extension_discovery/devtools.json new file mode 100644 index 00000000..571658ed --- /dev/null +++ b/packages/payments/.dart_tool/extension_discovery/devtools.json @@ -0,0 +1 @@ +{"version":2,"entries":[{"package":"design_system","rootUri":"../../design_system/","packageUri":"lib/"},{"package":"fonts","rootUri":"../../fonts/","packageUri":"lib/"},{"package":"get_it","rootUri":"file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/get_it-9.2.0/","packageUri":"lib/","config":{"name":"get_it","issueTracker":"https://github.com/fluttercommunity/get_it/issues","version":"0.0.1","materialIconCodePoint":"0xe189"}},{"package":"navigation","rootUri":"../../navigation/","packageUri":"lib/"},{"package":"sf_infrastructure","rootUri":"../../sf_infrastructure/","packageUri":"lib/"},{"package":"sf_localizations","rootUri":"../../sf_localizations/","packageUri":"lib/"},{"package":"shared_preferences","rootUri":"file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences-2.5.4/","packageUri":"lib/","config":{"name":"shared_preferences","issueTracker":"https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+shared_preferences%22","version":"1.0.0","materialIconCodePoint":"0xe683"}},{"package":"utils","rootUri":"../../utils/","packageUri":"lib/"},{"package":"payments","rootUri":"../","packageUri":"lib/"}]} \ No newline at end of file diff --git a/packages/payments/.dart_tool/package_config.json b/packages/payments/.dart_tool/package_config.json index 0d2a1494..74790dad 100644 --- a/packages/payments/.dart_tool/package_config.json +++ b/packages/payments/.dart_tool/package_config.json @@ -3,211 +3,211 @@ "packages": [ { "name": "_fe_analyzer_shared", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/_fe_analyzer_shared-85.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-85.0.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "analyzer", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/analyzer-7.6.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/analyzer-7.6.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "analyzer_buffer", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/analyzer_buffer-0.1.10", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/analyzer_buffer-0.1.10", "packageUri": "lib/", "languageVersion": "3.6" }, { "name": "analyzer_plugin", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/analyzer_plugin-0.13.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/analyzer_plugin-0.13.4", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "archive", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/archive-4.0.9", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/archive-4.0.9", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "args", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/args-2.7.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/args-2.7.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "async", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.13.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/async-2.13.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "boolean_selector", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/boolean_selector-2.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/boolean_selector-2.1.2", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "build", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build-3.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build-3.1.0", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "build_config", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_config-1.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_config-1.2.0", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "build_daemon", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_daemon-4.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_daemon-4.1.1", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "build_resolvers", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_resolvers-3.0.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_resolvers-3.0.3", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "build_runner", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_runner-2.7.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_runner-2.7.1", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "build_runner_core", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_runner_core-9.3.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_runner_core-9.3.1", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "built_collection", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/built_collection-5.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/built_collection-5.1.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "built_value", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/built_value-8.12.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/built_value-8.12.3", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "characters", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/characters-1.4.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/characters-1.4.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "checked_yaml", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/checked_yaml-2.0.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/checked_yaml-2.0.4", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "ci", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/ci-0.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/ci-0.1.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "cli_config", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cli_config-0.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cli_config-0.2.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "cli_util", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cli_util-0.4.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cli_util-0.4.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "clock", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/clock-1.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/clock-1.1.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "code_builder", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/code_builder-4.11.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/code_builder-4.11.1", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "collection", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/collection-1.19.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "confetti", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/confetti-0.7.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/confetti-0.7.0", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "convert", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/convert-3.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/convert-3.1.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "cookie_jar", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cookie_jar-4.0.8", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cookie_jar-4.0.8", "packageUri": "lib/", "languageVersion": "2.15" }, { "name": "country_code_picker", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/country_code_picker-3.4.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/country_code_picker-3.4.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "coverage", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/coverage-1.15.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/coverage-1.15.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "crypto", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/crypto-3.0.7", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/crypto-3.0.7", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "custom_lint", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/custom_lint-0.8.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/custom_lint-0.8.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "custom_lint_builder", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/custom_lint_builder-0.8.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/custom_lint_builder-0.8.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "custom_lint_core", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/custom_lint_core-0.8.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/custom_lint_core-0.8.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "custom_lint_visitor", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/custom_lint_visitor-1.0.0+7.7.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/custom_lint_visitor-1.0.0+7.7.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "dart_style", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dart_style-3.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dart_style-3.1.1", "packageUri": "lib/", "languageVersion": "3.7" }, @@ -219,79 +219,79 @@ }, { "name": "diacritic", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/diacritic-0.1.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/diacritic-0.1.6", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "dio", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dio-5.9.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dio-5.9.1", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "dio_cookie_manager", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dio_cookie_manager-3.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dio_cookie_manager-3.3.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "dio_web_adapter", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dio_web_adapter-2.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dio_web_adapter-2.1.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "fake_async", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/fake_async-1.3.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "ffi", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/ffi-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/ffi-2.2.0", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "file", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/file-7.0.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/file-7.0.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "fixnum", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/fixnum-1.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/fixnum-1.1.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "flutter", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "flutter_lints", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_lints-5.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_lints-5.0.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "flutter_riverpod", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_riverpod-3.0.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_riverpod-3.0.3", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "flutter_test", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter_test", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter_test", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "flutter_web_plugins", - "rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter_web_plugins", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter_web_plugins", "packageUri": "lib/", "languageVersion": "3.8" }, @@ -303,163 +303,163 @@ }, { "name": "freezed", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/freezed-3.2.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/freezed-3.2.3", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "freezed_annotation", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/freezed_annotation-3.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/freezed_annotation-3.1.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "frontend_server_client", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/frontend_server_client-4.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/frontend_server_client-4.0.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "get_it", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/get_it-9.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/get_it-9.2.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "glob", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/glob-2.1.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/glob-2.1.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "go_router", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/go_router-17.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/go_router-17.1.0", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "graphs", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/graphs-2.3.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/graphs-2.3.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "hotreloader", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/hotreloader-4.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/hotreloader-4.3.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "http", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http-1.6.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http-1.6.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "http_multi_server", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http_multi_server-3.2.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http_multi_server-3.2.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "http_parser", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http_parser-4.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http_parser-4.1.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "intl", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/intl-0.20.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/intl-0.20.2", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "io", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/io-1.0.5", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/io-1.0.5", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "js", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/js-0.7.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/js-0.7.2", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "json_annotation", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/json_annotation-4.9.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/json_annotation-4.9.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "json_serializable", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/json_serializable-6.11.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/json_serializable-6.11.2", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "leak_tracker", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker-11.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/leak_tracker-11.0.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "leak_tracker_flutter_testing", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.10", + "rootUri": "file:///Users/juliandalcalaf/.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/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_testing-3.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "lints", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/lints-5.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/lints-5.1.1", "packageUri": "lib/", "languageVersion": "3.6" }, { "name": "logging", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/logging-1.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/logging-1.3.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "lottie", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/lottie-3.3.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/lottie-3.3.2", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "matcher", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/matcher-0.12.17", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/matcher-0.12.17", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "material_color_utilities", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/material_color_utilities-0.11.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "meta", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.16.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/meta-1.16.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "mime", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/mime-2.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/mime-2.0.0", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "mockito", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/mockito-5.5.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/mockito-5.5.0", "packageUri": "lib/", "languageVersion": "3.7" }, @@ -471,127 +471,127 @@ }, { "name": "node_preamble", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/node_preamble-2.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/node_preamble-2.0.2", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "package_config", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/package_config-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/package_config-2.2.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "path", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path-1.9.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "path_provider", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider-2.1.5", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider-2.1.5", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "path_provider_android", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_android-2.2.22", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_android-2.2.22", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "path_provider_foundation", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_foundation-2.5.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_foundation-2.5.1", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "path_provider_linux", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.1", + "rootUri": "file:///Users/juliandalcalaf/.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/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_platform_interface-2.1.2", + "rootUri": "file:///Users/juliandalcalaf/.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/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_windows-2.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "platform", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/platform-3.1.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/platform-3.1.6", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "plugin_platform_interface", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/plugin_platform_interface-2.1.8", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "pool", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pool-1.5.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pool-1.5.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "posix", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/posix-6.5.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/posix-6.5.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "pub_semver", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pub_semver-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pub_semver-2.2.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "pubspec_parse", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_parse-1.5.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pubspec_parse-1.5.0", "packageUri": "lib/", "languageVersion": "3.6" }, { "name": "riverpod", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/riverpod-3.0.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/riverpod-3.0.3", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "riverpod_analyzer_utils", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/riverpod_analyzer_utils-1.0.0-dev.7", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/riverpod_analyzer_utils-1.0.0-dev.7", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "riverpod_annotation", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/riverpod_annotation-3.0.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/riverpod_annotation-3.0.3", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "riverpod_generator", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/riverpod_generator-3.0.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/riverpod_generator-3.0.3", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "riverpod_lint", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/riverpod_lint-3.0.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/riverpod_lint-3.0.3", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "rxdart", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/rxdart-0.28.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/rxdart-0.28.0", "packageUri": "lib/", "languageVersion": "2.12" }, @@ -609,181 +609,181 @@ }, { "name": "shared_preferences", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences-2.5.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences-2.5.4", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "shared_preferences_android", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_android-2.4.20", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.20", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "shared_preferences_foundation", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_foundation-2.5.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.6", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "shared_preferences_linux", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_linux-2.4.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "shared_preferences_platform_interface", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "shared_preferences_web", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_web-2.4.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "shared_preferences_windows", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_windows-2.4.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "shelf", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf-1.4.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf-1.4.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "shelf_packages_handler", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_packages_handler-3.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf_packages_handler-3.0.2", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "shelf_static", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_static-1.1.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf_static-1.1.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "shelf_web_socket", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_web_socket-3.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf_web_socket-3.0.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "sky_engine", - "rootUri": "file:///C:/Program%20Files/Flutter/bin/cache/pkg/sky_engine", + "rootUri": "file:///Users/juliandalcalaf/Development/flutter/bin/cache/pkg/sky_engine", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "source_gen", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_gen-3.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_gen-3.1.0", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "source_helper", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_helper-1.3.8", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_helper-1.3.8", "packageUri": "lib/", "languageVersion": "3.7" }, { "name": "source_map_stack_trace", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_map_stack_trace-2.1.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_map_stack_trace-2.1.2", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "source_maps", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_maps-0.10.13", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_maps-0.10.13", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "source_span", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_span-1.10.2", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "stack_trace", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stack_trace-1.12.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "state_notifier", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/state_notifier-1.0.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/state_notifier-1.0.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "stream_channel", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stream_channel-2.1.4", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stream_channel-2.1.4", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "stream_transform", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stream_transform-2.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stream_transform-2.1.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "string_scanner", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.4.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/string_scanner-1.4.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "term_glyph", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/term_glyph-1.2.2", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "test", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/test-1.26.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/test-1.26.2", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "test_api", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/test_api-0.7.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/test_api-0.7.6", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "test_core", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/test_core-0.6.11", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/test_core-0.6.11", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "timing", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/timing-1.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/timing-1.0.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "top_snackbar_flutter", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/top_snackbar_flutter-3.3.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/top_snackbar_flutter-3.3.0", "packageUri": "lib/", "languageVersion": "2.15" }, { "name": "typed_data", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/typed_data-1.4.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/typed_data-1.4.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "universal_io", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/universal_io-2.3.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/universal_io-2.3.1", "packageUri": "lib/", "languageVersion": "3.6" }, @@ -795,85 +795,85 @@ }, { "name": "uuid", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/uuid-4.5.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/uuid-4.5.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "vector_math", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_math-2.2.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_math-2.2.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "vm_service", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vm_service-15.0.2", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vm_service-15.0.2", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "watcher", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/watcher-1.2.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/watcher-1.2.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "web", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web-1.1.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web-1.1.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "web_socket", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket-1.0.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web_socket-1.0.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "web_socket_channel", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket_channel-3.0.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web_socket_channel-3.0.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "webkit_inspection_protocol", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/webkit_inspection_protocol-1.2.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/webkit_inspection_protocol-1.2.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "webview_flutter", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/webview_flutter-4.13.1", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/webview_flutter-4.13.1", "packageUri": "lib/", "languageVersion": "3.8" }, { "name": "webview_flutter_android", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/webview_flutter_android-4.10.11", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/webview_flutter_android-4.10.11", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "webview_flutter_platform_interface", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/webview_flutter_platform_interface-2.14.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/webview_flutter_platform_interface-2.14.0", "packageUri": "lib/", "languageVersion": "3.6" }, { "name": "webview_flutter_wkwebview", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/webview_flutter_wkwebview-3.23.6", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/webview_flutter_wkwebview-3.23.6", "packageUri": "lib/", "languageVersion": "3.9" }, { "name": "xdg_directories", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/xdg_directories-1.1.0", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "yaml", - "rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/yaml-3.1.3", + "rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/yaml-3.1.3", "packageUri": "lib/", "languageVersion": "3.4" }, @@ -886,7 +886,7 @@ ], "generator": "pub", "generatorVersion": "3.9.2", - "flutterRoot": "file:///C:/Program%20Files/Flutter", - "flutterVersion": "3.35.6", - "pubCache": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache" + "flutterRoot": "file:///Users/juliandalcalaf/Development/flutter", + "flutterVersion": "3.35.7", + "pubCache": "file:///Users/juliandalcalaf/.pub-cache" } diff --git a/packages/payments/.dart_tool/version b/packages/payments/.dart_tool/version index eb4861ac..e119acda 100644 --- a/packages/payments/.dart_tool/version +++ b/packages/payments/.dart_tool/version @@ -1 +1 @@ -3.35.6 \ No newline at end of file +3.35.7 \ No newline at end of file diff --git a/packages/payments/.flutter-plugins-dependencies b/packages/payments/.flutter-plugins-dependencies index c2ebc76f..76b0b485 100644 --- a/packages/payments/.flutter-plugins-dependencies +++ b/packages/payments/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.5.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"webview_flutter_wkwebview","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\webview_flutter_wkwebview-3.23.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.2.22\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_android-2.4.20\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"webview_flutter_android","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\webview_flutter_android-4.10.11\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.5.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"webview_flutter_wkwebview","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\webview_flutter_wkwebview-3.23.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.2.1\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_linux-2.4.1\\\\","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.3.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_windows-2.4.1\\\\","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false}],"web":[{"name":"shared_preferences_web","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_web-2.4.3\\\\","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2026-03-09 10:56:58.962073","version":"3.35.6","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_foundation-2.5.1/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.6/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"webview_flutter_wkwebview","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/webview_flutter_wkwebview-3.23.6/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"path_provider_android","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_android-2.2.22/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.20/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"webview_flutter_android","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/webview_flutter_android-4.10.11/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"path_provider_foundation","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_foundation-2.5.1/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.6/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"webview_flutter_wkwebview","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/webview_flutter_wkwebview-3.23.6/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"path_provider_linux","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false}],"windows":[{"name":"path_provider_windows","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false}],"web":[{"name":"shared_preferences_web","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2026-03-13 09:49:21.741790","version":"3.35.7","swift_package_manager_enabled":{"ios":false,"macos":false}} \ No newline at end of file diff --git a/packages/payments/devtools_options.yaml b/packages/payments/devtools_options.yaml new file mode 100644 index 00000000..fa0b357c --- /dev/null +++ b/packages/payments/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/packages/sf_localizations/assets/l10n/de.json b/packages/sf_localizations/assets/l10n/de.json index ef7963b2..ad61f3c1 100644 --- a/packages/sf_localizations/assets/l10n/de.json +++ b/packages/sf_localizations/assets/l10n/de.json @@ -488,5 +488,91 @@ "deviceSetup_weightHint": "30", "deviceSetup_heightLabel": "Größe (cm)", "deviceSetup_heightHint": "120", - "activationKeyLabel": "Aktivierungsschlüssel" + "activationKeyLabel": "Aktivierungsschlüssel", + "monday": "Montag", + "tuesday": "Dienstag", + "wednesday": "Mittwoch", + "thursday": "Donnerstag", + "friday": "Freitag", + "saturday": "Samstag", + "sunday": "Sonntag", + "scheduledActivityEmpty": "Keine geplanten Aktivitäten", + "scheduledActivityEmptyHint": "Tippe auf +, um die erste Aktivität im Kalender zu erstellen", + "scheduledActivityStartTime": "Beginn", + "scheduledActivityEndTime": "Ende", + "scheduledActivityStartBeforeEnd": "Die Startzeit muss vor der Endzeit liegen", + "scheduledActivityOverlap": "Überschneidung mit „{name}" ({time})", + "scheduledActivityNewTitle": "Neue Aktivität", + "scheduledActivityEditTitle": "Aktivität bearbeiten", + "scheduledActivityDeleteTitle": "Aktivität löschen", + "scheduledActivityDeleteMessage": "Möchten Sie \"{name}\" wirklich löschen?", + "mainContactPhoneNumber": "Telefonnummer des Hauptkontakts", + "loadingPhoto": "Foto wird geladen...", + "editContact": "Kontakt bearbeiten", + "sending": "Wird gesendet...", + "sentSuccessfully": "Erfolgreich gesendet", + "deviceNotConnected": "Das Gerät ist nicht mit dem Internet verbunden", + "ok": "OK", + "locateDeviceConfirmMessage": "Sie werden den Fernstandort Ihres Geräts aktivieren. Es wird anfangen zu klingeln.", + "continueWithGoogle": "Weiter mit Google", + "redirectingToGoogle": "Weiterleitung zu Google", + "errorMessagePhoneIsInvalid": "Ungültiges Telefonnummernformat", + "contactsEmpty": "Keine Kontakte", + "contactsEmptyHint": "Tippe auf +, um einen Kontakt hinzuzufügen", + "activityMeter": "Aktivitätsmesser", + "totalSteps": "Gesamtschritte", + "bestDay": "Bester Tag", + "steps": "Schritte", + "rewards": "Belohnungen senden", + "rewardsMessage": "*Mit dieser Funktion kannst du dein Kind für erreichte Ziele oder gute Taten belohnen.", + "sendRewards": "Belohnungen senden!", + "rewardsSent": "Belohnungen gesendet!", + "appsUse": "App-Nutzung", + "topApps": "Meistgenutzte Apps", + "noAppUsageData": "Keine App-Nutzungsdaten verfügbar", + "selectDay": "Tage auswählen", + "alarmMessage": "Nachricht", + "alarmMessageHint": "Text, den der Alarm anzeigen wird", + "deleteAlarm": "Alarm löschen", + "deleteAlarmConfirm": "Möchten Sie diesen Alarm wirklich löschen?", + "editAlarm": "Alarm bearbeiten", + "noAlarms": "Keine Alarme konfiguriert", + "alarmCreated": "Alarm erfolgreich erstellt", + "alarmUpdated": "Alarm erfolgreich aktualisiert", + "alarmDeleted": "Alarm erfolgreich gelöscht", + "noActivityData": "Keine Aktivitätsmessungen vorhanden", + "phone": "Telefon", + "add": "Hinzufügen", + "contactName": "Kontaktname", + "addAllowedNumber": "Erlaubte Nummer hinzufügen", + "noBlockedNumbers": "Keine Nummern konfiguriert", + "noBlockedNumbersDescription": "Fügen Sie Nummern hinzu, um einzuschränken, wer mit dem Gerät kommunizieren kann", + "whitelistDescription": "Nur diese Nummern können mit dem Gerät kommunizieren", + "allowedNumbersCount": "{count} erlaubte Nummern", + "removeAllowedNumber": "Erlaubte Nummer entfernen", + "removeAllowedNumberConfirm": "\"{name}\" aus der Liste der erlaubten Nummern entfernen? Diese Nummer kann nicht mehr mit dem Gerät kommunizieren", + "numberAdded": "Nummer erfolgreich hinzugefügt", + "numberRemoved": "Nummer erfolgreich entfernt", + "addSosContact": "SOS-Kontakt hinzufügen", + "noSosContacts": "Keine SOS-Kontakte konfiguriert", + "noSosContactsDescription": "Fügen Sie Notfallkontakte hinzu, die das Gerät im Notfall anrufen kann", + "sosDescription": "Diese Kontakte sind für Notrufe vom Gerät aus verfügbar", + "sosContactsCount": "{count} SOS-Kontakte", + "removeSosContact": "SOS-Kontakt entfernen", + "removeSosContactConfirm": "\"{name}\" aus der SOS-Kontaktliste entfernen? Dieser Kontakt ist nicht mehr für Notrufe verfügbar", + "sosNumberAdded": "SOS-Kontakt erfolgreich hinzugefügt", + "sosNumberRemoved": "SOS-Kontakt erfolgreich entfernt", + "addWifiNetwork": "WLAN-Netzwerk hinzufügen", + "noWifiNetworks": "Keine WLAN-Netzwerke konfiguriert", + "noWifiNetworksDescription": "Fügen Sie WLAN-Netzwerke hinzu, mit denen sich das Gerät automatisch verbinden kann", + "wifiDescription": "Das Gerät verbindet sich automatisch mit diesen WLAN-Netzwerken, wenn es in Reichweite ist", + "wifiNetworksCount": "{count} WLAN-Netzwerke", + "removeWifiNetwork": "WLAN-Netzwerk entfernen", + "removeWifiNetworkConfirm": "\"{name}\" aus der WLAN-Netzwerkliste entfernen? Das Gerät wird sich nicht mehr automatisch mit diesem Netzwerk verbinden", + "wifiNetworkAdded": "WLAN-Netzwerk erfolgreich hinzugefügt", + "wifiNetworkRemoved": "WLAN-Netzwerk erfolgreich entfernt", + "wifiSsid": "Netzwerkname (SSID)", + "wifiBssid": "MAC-Adresse (BSSID)", + "wifiSsidHint": "z.B. MeinHeimWLAN", + "wifiBssidHint": "z.B. 0c:80:63:e4:cb:e1" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/en.json b/packages/sf_localizations/assets/l10n/en.json index fc942068..7efbb733 100755 --- a/packages/sf_localizations/assets/l10n/en.json +++ b/packages/sf_localizations/assets/l10n/en.json @@ -517,10 +517,31 @@ "doNotDisturb": "Do not disturb", "videoCall": "Video call", "health": "Health", + "healthEmpty": "No health data", + "healthEmptyHint": "Data will sync automatically from the device", + "heartRate": "Heart rate", + "bloodPressure": "Blood pressure", + "oxygenLevel": "Blood oxygen", + "bpm": "bpm", + "mmHg": "mmHg", + "spo2": "SpO2", + "noData": "No data", + "today": "Today", + "yesterday": "Yesterday", + "lastReading": "Last reading", + "timeAgo": "{time} ago", + "sevenDays": "7d", + "thirtyDays": "30d", + "custom": "Custom", + "average": "Average", + "minimum": "Min", + "maximum": "Max", + "history": "History", "activityMeter": "Activity meter", "rewards": "Rewards", "callWatch": "Call watch", "appsUse": "Apps use", + "topApps": "Top apps", "appsSurveillance": "Apps surveillance", "makeFriends": "Make friends", "locateSF": "Play sound on device", @@ -543,15 +564,31 @@ "deviceSetup_heightLabel": "Height (cm)", "deviceSetup_heightHint": "120", "activationKeyLabel": "Activation key", - "rewardsMessage": "Send rewards", + "rewardsMessage": "*Using this feature you can reward your child for goals achieved or good actions.", "sendRewards": "Send rewards!", + "rewardsSent": "Rewards sent!", "male": "Male", "female": "Female", "ratherNotSay": "I'd rather not say", "personalDataMessage": "*This is the app user's personal data", "newContact": "New contact", "deleteContactMessage": "Are you sure you want to delete this phone from the list?", - "remoteListening": "Remote Listening", + "settings": "Settings", + "alarm": "Alarms", + "appStore": "App Store", + "battery": "Night Battery Saver", + "blockPhone": "Number Blocking", + "disableFunctions": "Disable Functions", + "language": "Language", + "legacyNotifications": "Notifications", + "remoteManagement": "Remote Management", + "remoteOnOff": "Scheduled On/Off", + "smsAlert": "SMS Alerts", + "sosContacts": "SOS Contacts", + "sound": "Sounds", + "syncClock": "Time Sync", + "timezone": "Timezone", + "wifiSettings": "WiFi Settings", "alarmSettings": "Alarm settings", "setDateTime": "Set time and days:", "addAlarm": "Add new alarm", @@ -559,6 +596,15 @@ "once": "Once", "daily": "Daily", "selectDay": "Select days", + "alarmMessage": "Message", + "alarmMessageHint": "Text the alarm will display", + "deleteAlarm": "Delete alarm", + "deleteAlarmConfirm": "Are you sure you want to delete this alarm?", + "editAlarm": "Edit alarm", + "noAlarms": "No alarms configured", + "alarmCreated": "Alarm created successfully", + "alarmUpdated": "Alarm updated successfully", + "alarmDeleted": "Alarm deleted successfully", "remoteTurnOff": "Apagado Remoto", "remoteTurnOffMessage": "Remote Shutdown", "remoteTurnOffConfirm": "Remotely shut down the device.", @@ -568,5 +614,74 @@ "remoteFactoryReset": "Are you sure you want to remotely restart the device?", "remoteFactoryResetMessage": "Restore Default Settings", "remoteFactoryResetConfirm": "Restore your device to factory settings?", - "number": "Number {num}:" + "number": "Number {num}:", + "monday": "Monday", + "tuesday": "Tuesday", + "wednesday": "Wednesday", + "thursday": "Thursday", + "friday": "Friday", + "saturday": "Saturday", + "sunday": "Sunday", + "scheduledActivityEmpty": "No scheduled activities", + "scheduledActivityEmptyHint": "Tap + to create the first activity in the calendar", + "scheduledActivityStartTime": "Start", + "scheduledActivityEndTime": "End", + "scheduledActivityStartBeforeEnd": "Start time must be before end time", + "scheduledActivityOverlap": "Overlaps with \"{name}\" ({time})", + "scheduledActivityNewTitle": "New activity", + "scheduledActivityEditTitle": "Edit activity", + "scheduledActivityDeleteTitle": "Delete activity", + "scheduledActivityDeleteMessage": "Are you sure you want to delete \"{name}\"?", + "mainContactPhoneNumber": "Main contact phone number", + "loadingPhoto": "Loading photo...", + "editContact": "Edit Contact", + "sending": "Sending...", + "sentSuccessfully": "Sent successfully", + "deviceNotConnected": "The device is not connected to the Internet", + "ok": "OK", + "locateDeviceConfirmMessage": "You are going to activate the remote location of your device. It will start ringing.", + "continueWithGoogle": "Continue with Google", + "redirectingToGoogle": "Redirecting to Google", + "errorMessagePhoneIsInvalid": "Invalid phone number format", + "contactsEmpty": "No contacts", + "contactsEmptyHint": "Tap + to add a contact", + "totalSteps": "Total steps", + "bestDay": "Best day", + "steps": "steps", + "noAppUsageData": "No app usage data available", + "noActivityData": "No activity measurements to display", + "phone": "Phone", + "add": "Add", + "contactName": "Contact name", + "addAllowedNumber": "Add allowed number", + "noBlockedNumbers": "No numbers configured", + "noBlockedNumbersDescription": "Add numbers to restrict who can communicate with the device", + "whitelistDescription": "Only these numbers can communicate with the device", + "allowedNumbersCount": "{count} allowed numbers", + "removeAllowedNumber": "Remove allowed number", + "removeAllowedNumberConfirm": "Remove \"{name}\" from the allowed numbers list? This number will no longer be able to communicate with the device", + "numberAdded": "Number added successfully", + "numberRemoved": "Number removed successfully", + "addSosContact": "Add SOS contact", + "noSosContacts": "No SOS contacts configured", + "noSosContactsDescription": "Add emergency contacts that the device can call in case of emergency", + "sosDescription": "These contacts will be available for emergency calls from the device", + "sosContactsCount": "{count} SOS contacts", + "removeSosContact": "Remove SOS contact", + "removeSosContactConfirm": "Remove \"{name}\" from the SOS contacts list? This contact will no longer be available for emergency calls", + "sosNumberAdded": "SOS contact added successfully", + "sosNumberRemoved": "SOS contact removed successfully", + "addWifiNetwork": "Add WiFi network", + "noWifiNetworks": "No WiFi networks configured", + "noWifiNetworksDescription": "Add WiFi networks that the device can connect to automatically", + "wifiDescription": "The device will automatically connect to these WiFi networks when in range", + "wifiNetworksCount": "{count} WiFi networks", + "removeWifiNetwork": "Remove WiFi network", + "removeWifiNetworkConfirm": "Remove \"{name}\" from the WiFi networks list? The device will no longer connect to this network automatically", + "wifiNetworkAdded": "WiFi network added successfully", + "wifiNetworkRemoved": "WiFi network removed successfully", + "wifiSsid": "Network name (SSID)", + "wifiBssid": "MAC address (BSSID)", + "wifiSsidHint": "e.g. MyHomeWiFi", + "wifiBssidHint": "e.g. 0c:80:63:e4:cb:e1" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/es.json b/packages/sf_localizations/assets/l10n/es.json index 2b826bcf..00caf985 100644 --- a/packages/sf_localizations/assets/l10n/es.json +++ b/packages/sf_localizations/assets/l10n/es.json @@ -515,10 +515,31 @@ "doNotDisturb": "No molestar", "videoCall": "Video llamada", "health": "Salud", + "healthEmpty": "Sin datos de salud", + "healthEmptyHint": "Los datos se sincronizarán automáticamente desde el dispositivo", + "heartRate": "Ritmo cardíaco", + "bloodPressure": "Presión arterial", + "oxygenLevel": "Oxígeno en sangre", + "bpm": "ppm", + "mmHg": "mmHg", + "spo2": "SpO2", + "noData": "Sin datos", + "today": "Hoy", + "yesterday": "Ayer", + "lastReading": "Última lectura", + "timeAgo": "hace {time}", + "sevenDays": "7d", + "thirtyDays": "30d", + "custom": "Personalizado", + "average": "Promedio", + "minimum": "Mínimo", + "maximum": "Máximo", + "history": "Historial", "activityMeter": "Medidor de actividad", "rewards": "Enviar recompensas", "callWatch": "Llamar al reloj", "appsUse": "Uso de las aplicaciones", + "topApps": "Apps más usadas", "appsSurveillance": "Supervisión de las aplicaciones", "makeFriends": "Hacer amigos", "locateSF": "Reproducir sonido en dispositivo", @@ -541,8 +562,9 @@ "deviceSetup_heightLabel": "Altura (cm)", "deviceSetup_heightHint": "120", "activationKeyLabel": "Clave de activación", - "rewardsMessage": "Envía una recompensa", + "rewardsMessage": "*Usando esta función puedes recompensar a tu hijo por metas alcanzadas o buenas acciones.", "sendRewards": "¡Enviar recompensas!", + "rewardsSent": "¡Recompensas enviadas!", "male": "Hombre", "female": "Mujer", "ratherNotSay": "Prefiero no decirlo", @@ -572,6 +594,15 @@ "once": "Una vez", "daily": "Diario", "selectDay": "Selección de días", + "alarmMessage": "Mensaje", + "alarmMessageHint": "Texto que mostrará la alarma", + "deleteAlarm": "Eliminar alarma", + "deleteAlarmConfirm": "¿Seguro que deseas eliminar esta alarma?", + "editAlarm": "Editar alarma", + "noAlarms": "No hay alarmas configuradas", + "alarmCreated": "Alarma creada correctamente", + "alarmUpdated": "Alarma actualizada correctamente", + "alarmDeleted": "Alarma eliminada correctamente", "remoteTurnOff": "Apagado Remoto", "remoteTurnOffMessage": "Apaga el dispositivo de forma remota", "remoteTurnOffConfirm": "¿Seguro que deseas apagar el dispositivo en remoto?", @@ -582,20 +613,73 @@ "remoteFactoryResetMessage": "Restaura tu dispositivo a la configuración de fábrica", "remoteFactoryResetConfirm": "¿Seguro que quieres restablecer este dispositivo a la configuración de fábrica?", "number": "Número {num}:", - "settings": "Ajustes", - "alarm": "Alarmas", - "appStore": "App Store", - "blockPhone": "Bloqueo de números", - "timezone": "Cambio de horario y zona", - "language": "Idioma", - "battery": "Ahorro nocturno de batería", - "remoteManagement": "programación remota", - "legacyNotifications": "notificaciones", - "smsAlert": "Alertas SMS", - "sosContacts": "Agenda SOS", - "sound": "Sonidos", - "wifiSettings": "Cofiguración WiFi", - "remoteOnOff": "Encendido y apagado programado", - "disableFunctions": "Deshabilitar funciones", - "syncClock": "Sincronización de tiempo" + "monday": "Lunes", + "tuesday": "Martes", + "wednesday": "Miércoles", + "thursday": "Jueves", + "friday": "Viernes", + "saturday": "Sábado", + "sunday": "Domingo", + "scheduledActivityEmpty": "No hay actividades programadas", + "scheduledActivityEmptyHint": "Pulsa + para crear la primera actividad del calendario", + "scheduledActivityStartTime": "Inicio", + "scheduledActivityEndTime": "Fin", + "scheduledActivityStartBeforeEnd": "La hora de inicio debe ser anterior a la hora de fin", + "scheduledActivityOverlap": "Se superpone con \"{name}\" ({time})", + "scheduledActivityNewTitle": "Nueva actividad", + "scheduledActivityEditTitle": "Editar actividad", + "scheduledActivityDeleteTitle": "Eliminar actividad", + "scheduledActivityDeleteMessage": "¿Seguro que quieres eliminar \"{name}\"?", + "mainContactPhoneNumber": "Número de teléfono del contacto principal", + "loadingPhoto": "Cargando foto...", + "editContact": "Editar contacto", + "sending": "Enviando...", + "sentSuccessfully": "Enviado correctamente", + "deviceNotConnected": "El dispositivo no está conectado a Internet", + "ok": "OK", + "locateDeviceConfirmMessage": "Vas a activar la localización remota de tu dispositivo. Comenzará a sonar.", + "continueWithGoogle": "Continuar con Google", + "redirectingToGoogle": "Redirigiendo a Google", + "errorMessagePhoneIsInvalid": "Formato de número de teléfono inválido", + "contactsEmpty": "No hay contactos", + "contactsEmptyHint": "Pulsa + para agregar un contacto", + "totalSteps": "Total pasos", + "bestDay": "Mejor día", + "steps": "pasos", + "noAppUsageData": "No hay datos de uso de aplicaciones", + "noActivityData": "No hay mediciones de actividad que mostrar", + "phone": "Teléfono", + "add": "Añadir", + "contactName": "Nombre del contacto", + "addAllowedNumber": "Añadir número permitido", + "noBlockedNumbers": "No hay números configurados", + "noBlockedNumbersDescription": "Añade números para restringir quién puede comunicarse con el dispositivo", + "whitelistDescription": "Solo estos números pueden comunicarse con el dispositivo", + "allowedNumbersCount": "{count} números permitidos", + "removeAllowedNumber": "Eliminar número permitido", + "removeAllowedNumberConfirm": "¿Eliminar \"{name}\" de la lista de números permitidos? Este número ya no podrá comunicarse con el dispositivo", + "numberAdded": "Número añadido correctamente", + "numberRemoved": "Número eliminado correctamente", + "addSosContact": "Añadir contacto SOS", + "noSosContacts": "No hay contactos SOS configurados", + "noSosContactsDescription": "Añade contactos de emergencia a los que el dispositivo pueda llamar en caso de emergencia", + "sosDescription": "Estos contactos estarán disponibles para llamadas de emergencia desde el dispositivo", + "sosContactsCount": "{count} contactos SOS", + "removeSosContact": "Eliminar contacto SOS", + "removeSosContactConfirm": "¿Eliminar \"{name}\" de la lista de contactos SOS? Este contacto ya no estará disponible para llamadas de emergencia", + "sosNumberAdded": "Contacto SOS añadido correctamente", + "sosNumberRemoved": "Contacto SOS eliminado correctamente", + "addWifiNetwork": "Añadir red WiFi", + "noWifiNetworks": "No hay redes WiFi configuradas", + "noWifiNetworksDescription": "Añade redes WiFi a las que el dispositivo pueda conectarse automáticamente", + "wifiDescription": "El dispositivo se conectará automáticamente a estas redes WiFi cuando esté dentro del alcance", + "wifiNetworksCount": "{count} redes WiFi", + "removeWifiNetwork": "Eliminar red WiFi", + "removeWifiNetworkConfirm": "¿Eliminar \"{name}\" de la lista de redes WiFi? El dispositivo ya no se conectará a esta red automáticamente", + "wifiNetworkAdded": "Red WiFi añadida correctamente", + "wifiNetworkRemoved": "Red WiFi eliminada correctamente", + "wifiSsid": "Nombre de red (SSID)", + "wifiBssid": "Dirección MAC (BSSID)", + "wifiSsidHint": "ej. MiWiFiCasa", + "wifiBssidHint": "ej. 0c:80:63:e4:cb:e1" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/fr.json b/packages/sf_localizations/assets/l10n/fr.json index d031dd92..616f30e8 100644 --- a/packages/sf_localizations/assets/l10n/fr.json +++ b/packages/sf_localizations/assets/l10n/fr.json @@ -488,5 +488,91 @@ "deviceSetup_weightHint": "30", "deviceSetup_heightLabel": "Taille (cm)", "deviceSetup_heightHint": "120", - "activationKeyLabel": "Clé d'activation" + "activationKeyLabel": "Clé d'activation", + "monday": "Lundi", + "tuesday": "Mardi", + "wednesday": "Mercredi", + "thursday": "Jeudi", + "friday": "Vendredi", + "saturday": "Samedi", + "sunday": "Dimanche", + "scheduledActivityEmpty": "Aucune activité programmée", + "scheduledActivityEmptyHint": "Appuyez sur + pour créer la première activité du calendrier", + "scheduledActivityStartTime": "Début", + "scheduledActivityEndTime": "Fin", + "scheduledActivityStartBeforeEnd": "L'heure de début doit être antérieure à l'heure de fin", + "scheduledActivityOverlap": "Chevauche « {name} » ({time})", + "scheduledActivityNewTitle": "Nouvelle activité", + "scheduledActivityEditTitle": "Modifier l'activité", + "scheduledActivityDeleteTitle": "Supprimer l'activité", + "scheduledActivityDeleteMessage": "Voulez-vous vraiment supprimer \"{name}\" ?", + "mainContactPhoneNumber": "Numéro de téléphone du contact principal", + "loadingPhoto": "Chargement de la photo...", + "editContact": "Modifier le contact", + "sending": "Envoi en cours...", + "sentSuccessfully": "Envoyé avec succès", + "deviceNotConnected": "L'appareil n'est pas connecté à Internet", + "ok": "OK", + "locateDeviceConfirmMessage": "Vous allez activer la localisation à distance de votre appareil. Il va commencer à sonner.", + "continueWithGoogle": "Continuer avec Google", + "redirectingToGoogle": "Redirection vers Google", + "errorMessagePhoneIsInvalid": "Format de numéro de téléphone invalide", + "contactsEmpty": "Aucun contact", + "contactsEmptyHint": "Appuyez sur + pour ajouter un contact", + "activityMeter": "Compteur d'activité", + "totalSteps": "Total des pas", + "bestDay": "Meilleur jour", + "steps": "pas", + "rewards": "Envoyer des récompenses", + "rewardsMessage": "*En utilisant cette fonction, vous pouvez récompenser votre enfant pour des objectifs atteints ou de bonnes actions.", + "sendRewards": "Envoyer des récompenses !", + "rewardsSent": "Récompenses envoyées !", + "appsUse": "Utilisation des applications", + "topApps": "Applications les plus utilisées", + "noAppUsageData": "Aucune donnée d'utilisation des applications", + "selectDay": "Sélection des jours", + "alarmMessage": "Message", + "alarmMessageHint": "Texte que l'alarme affichera", + "deleteAlarm": "Supprimer l'alarme", + "deleteAlarmConfirm": "Êtes-vous sûr de vouloir supprimer cette alarme ?", + "editAlarm": "Modifier l'alarme", + "noAlarms": "Aucune alarme configurée", + "alarmCreated": "Alarme créée avec succès", + "alarmUpdated": "Alarme mise à jour avec succès", + "alarmDeleted": "Alarme supprimée avec succès", + "noActivityData": "Aucune mesure d'activité à afficher", + "phone": "Téléphone", + "add": "Ajouter", + "contactName": "Nom du contact", + "addAllowedNumber": "Ajouter un numéro autorisé", + "noBlockedNumbers": "Aucun numéro configuré", + "noBlockedNumbersDescription": "Ajoutez des numéros pour restreindre qui peut communiquer avec l'appareil", + "whitelistDescription": "Seuls ces numéros peuvent communiquer avec l'appareil", + "allowedNumbersCount": "{count} numéros autorisés", + "removeAllowedNumber": "Supprimer le numéro autorisé", + "removeAllowedNumberConfirm": "Supprimer \"{name}\" de la liste des numéros autorisés ? Ce numéro ne pourra plus communiquer avec l'appareil", + "numberAdded": "Numéro ajouté avec succès", + "numberRemoved": "Numéro supprimé avec succès", + "addSosContact": "Ajouter un contact SOS", + "noSosContacts": "Aucun contact SOS configuré", + "noSosContactsDescription": "Ajoutez des contacts d'urgence que l'appareil peut appeler en cas d'urgence", + "sosDescription": "Ces contacts seront disponibles pour les appels d'urgence depuis l'appareil", + "sosContactsCount": "{count} contacts SOS", + "removeSosContact": "Supprimer le contact SOS", + "removeSosContactConfirm": "Supprimer \"{name}\" de la liste des contacts SOS ? Ce contact ne sera plus disponible pour les appels d'urgence", + "sosNumberAdded": "Contact SOS ajouté avec succès", + "sosNumberRemoved": "Contact SOS supprimé avec succès", + "addWifiNetwork": "Ajouter un réseau WiFi", + "noWifiNetworks": "Aucun réseau WiFi configuré", + "noWifiNetworksDescription": "Ajoutez des réseaux WiFi auxquels l'appareil peut se connecter automatiquement", + "wifiDescription": "L'appareil se connectera automatiquement à ces réseaux WiFi lorsqu'il sera à portée", + "wifiNetworksCount": "{count} réseaux WiFi", + "removeWifiNetwork": "Supprimer le réseau WiFi", + "removeWifiNetworkConfirm": "Supprimer \"{name}\" de la liste des réseaux WiFi ? L'appareil ne se connectera plus automatiquement à ce réseau", + "wifiNetworkAdded": "Réseau WiFi ajouté avec succès", + "wifiNetworkRemoved": "Réseau WiFi supprimé avec succès", + "wifiSsid": "Nom du réseau (SSID)", + "wifiBssid": "Adresse MAC (BSSID)", + "wifiSsidHint": "ex. MonWiFiMaison", + "wifiBssidHint": "ex. 0c:80:63:e4:cb:e1" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/it.json b/packages/sf_localizations/assets/l10n/it.json index e9690358..c4315e1d 100644 --- a/packages/sf_localizations/assets/l10n/it.json +++ b/packages/sf_localizations/assets/l10n/it.json @@ -163,7 +163,7 @@ "deviceSetup_linkTroubleshoot_title": "Se non riesci a collegare il cinturino o l'orologio", "legacy_deviceSetup_scanWatch_title": "Collega l'orologio", "legacy_deviceSetup_linkTroubleshoot_title": "Se non riesci a collegare l'orologio", - "deviceSetup_contactUs": "Contactez-nous", + "deviceSetup_contactUs": "Contattaci", "deviceSetup_accountData_info": "Abbiamo bisogno di questi dati per creare il suo conto e gestire paghette e spese", "legacy_deviceSetup_accountData_info": "Abbiamo bisogno di questi dati per creare il suo conto", "deviceSetup_startWithOneKid_info": "Inizia con un bambino, poi potrai aggiungerne altri", @@ -488,5 +488,91 @@ "deviceSetup_weightHint": "30", "deviceSetup_heightLabel": "Altezza (cm)", "deviceSetup_heightHint": "120", - "activationKeyLabel": "Chiave di attivazione" + "activationKeyLabel": "Chiave di attivazione", + "monday": "Lunedì", + "tuesday": "Martedì", + "wednesday": "Mercoledì", + "thursday": "Giovedì", + "friday": "Venerdì", + "saturday": "Sabato", + "sunday": "Domenica", + "scheduledActivityEmpty": "Nessuna attività programmata", + "scheduledActivityEmptyHint": "Premi + per creare la prima attività nel calendario", + "scheduledActivityStartTime": "Inizio", + "scheduledActivityEndTime": "Fine", + "scheduledActivityStartBeforeEnd": "L'orario di inizio deve essere precedente all'orario di fine", + "scheduledActivityOverlap": "Si sovrappone con \"{name}\" ({time})", + "scheduledActivityNewTitle": "Nuova attività", + "scheduledActivityEditTitle": "Modifica attività", + "scheduledActivityDeleteTitle": "Elimina attività", + "scheduledActivityDeleteMessage": "Sei sicuro di voler eliminare \"{name}\"?", + "mainContactPhoneNumber": "Numero di telefono del contatto principale", + "loadingPhoto": "Caricamento foto...", + "editContact": "Modifica contatto", + "sending": "Invio in corso...", + "sentSuccessfully": "Inviato con successo", + "deviceNotConnected": "Il dispositivo non è connesso a Internet", + "ok": "OK", + "locateDeviceConfirmMessage": "Stai per attivare la localizzazione remota del tuo dispositivo. Inizierà a suonare.", + "continueWithGoogle": "Continua con Google", + "redirectingToGoogle": "Reindirizzamento a Google", + "errorMessagePhoneIsInvalid": "Formato del numero di telefono non valido", + "contactsEmpty": "Nessun contatto", + "contactsEmptyHint": "Premi + per aggiungere un contatto", + "activityMeter": "Contatore attività", + "totalSteps": "Passi totali", + "bestDay": "Giorno migliore", + "steps": "passi", + "rewards": "Invia ricompense", + "rewardsMessage": "*Usando questa funzione puoi premiare tuo figlio per obiettivi raggiunti o buone azioni.", + "sendRewards": "Invia ricompense!", + "rewardsSent": "Ricompense inviate!", + "appsUse": "Utilizzo delle applicazioni", + "topApps": "App più utilizzate", + "noAppUsageData": "Nessun dato sull'utilizzo delle app", + "selectDay": "Selezione dei giorni", + "alarmMessage": "Messaggio", + "alarmMessageHint": "Testo che l'allarme mostrerà", + "deleteAlarm": "Elimina allarme", + "deleteAlarmConfirm": "Sei sicuro di voler eliminare questo allarme?", + "editAlarm": "Modifica allarme", + "noAlarms": "Nessun allarme configurato", + "alarmCreated": "Allarme creato con successo", + "alarmUpdated": "Allarme aggiornato con successo", + "alarmDeleted": "Allarme eliminato con successo", + "noActivityData": "Nessuna misurazione di attività da mostrare", + "phone": "Telefono", + "add": "Aggiungi", + "contactName": "Nome del contatto", + "addAllowedNumber": "Aggiungi numero consentito", + "noBlockedNumbers": "Nessun numero configurato", + "noBlockedNumbersDescription": "Aggiungi numeri per limitare chi può comunicare con il dispositivo", + "whitelistDescription": "Solo questi numeri possono comunicare con il dispositivo", + "allowedNumbersCount": "{count} numeri consentiti", + "removeAllowedNumber": "Rimuovi numero consentito", + "removeAllowedNumberConfirm": "Rimuovere \"{name}\" dall'elenco dei numeri consentiti? Questo numero non potrà più comunicare con il dispositivo", + "numberAdded": "Numero aggiunto con successo", + "numberRemoved": "Numero rimosso con successo", + "addSosContact": "Aggiungi contatto SOS", + "noSosContacts": "Nessun contatto SOS configurato", + "noSosContactsDescription": "Aggiungi contatti di emergenza che il dispositivo può chiamare in caso di emergenza", + "sosDescription": "Questi contatti saranno disponibili per le chiamate di emergenza dal dispositivo", + "sosContactsCount": "{count} contatti SOS", + "removeSosContact": "Rimuovi contatto SOS", + "removeSosContactConfirm": "Rimuovere \"{name}\" dall'elenco dei contatti SOS? Questo contatto non sarà più disponibile per le chiamate di emergenza", + "sosNumberAdded": "Contatto SOS aggiunto con successo", + "sosNumberRemoved": "Contatto SOS rimosso con successo", + "addWifiNetwork": "Aggiungi rete WiFi", + "noWifiNetworks": "Nessuna rete WiFi configurata", + "noWifiNetworksDescription": "Aggiungi reti WiFi a cui il dispositivo può connettersi automaticamente", + "wifiDescription": "Il dispositivo si connetterà automaticamente a queste reti WiFi quando sarà nel raggio d'azione", + "wifiNetworksCount": "{count} reti WiFi", + "removeWifiNetwork": "Rimuovi rete WiFi", + "removeWifiNetworkConfirm": "Rimuovere \"{name}\" dall'elenco delle reti WiFi? Il dispositivo non si connetterà più automaticamente a questa rete", + "wifiNetworkAdded": "Rete WiFi aggiunta con successo", + "wifiNetworkRemoved": "Rete WiFi rimossa con successo", + "wifiSsid": "Nome rete (SSID)", + "wifiBssid": "Indirizzo MAC (BSSID)", + "wifiSsidHint": "es. MiaReteCasa", + "wifiBssidHint": "es. 0c:80:63:e4:cb:e1" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/pt.json b/packages/sf_localizations/assets/l10n/pt.json index f9ca20ce..ad39d423 100644 --- a/packages/sf_localizations/assets/l10n/pt.json +++ b/packages/sf_localizations/assets/l10n/pt.json @@ -488,5 +488,91 @@ "deviceSetup_weightHint": "30", "deviceSetup_heightLabel": "Altura (cm)", "deviceSetup_heightHint": "120", - "activationKeyLabel": "Chave de ativação" + "activationKeyLabel": "Chave de ativação", + "monday": "Segunda-feira", + "tuesday": "Terça-feira", + "wednesday": "Quarta-feira", + "thursday": "Quinta-feira", + "friday": "Sexta-feira", + "saturday": "Sábado", + "sunday": "Domingo", + "scheduledActivityEmpty": "Nenhuma atividade programada", + "scheduledActivityEmptyHint": "Toca + para criar a primeira atividade no calendário", + "scheduledActivityStartTime": "Início", + "scheduledActivityEndTime": "Fim", + "scheduledActivityStartBeforeEnd": "A hora de início deve ser anterior à hora de fim", + "scheduledActivityOverlap": "Sobrepõe-se com \"{name}\" ({time})", + "scheduledActivityNewTitle": "Nova atividade", + "scheduledActivityEditTitle": "Editar atividade", + "scheduledActivityDeleteTitle": "Eliminar atividade", + "scheduledActivityDeleteMessage": "Tem a certeza que deseja eliminar \"{name}\"?", + "mainContactPhoneNumber": "Número de telefone do contacto principal", + "loadingPhoto": "A carregar foto...", + "editContact": "Editar contacto", + "sending": "A enviar...", + "sentSuccessfully": "Enviado com sucesso", + "deviceNotConnected": "O dispositivo não está ligado à Internet", + "ok": "OK", + "locateDeviceConfirmMessage": "Vai ativar a localização remota do seu dispositivo. Ele começará a tocar.", + "continueWithGoogle": "Continuar com Google", + "redirectingToGoogle": "A redirecionar para Google", + "errorMessagePhoneIsInvalid": "Formato de número de telefone inválido", + "contactsEmpty": "Sem contactos", + "contactsEmptyHint": "Toca + para adicionar um contacto", + "activityMeter": "Medidor de atividade", + "totalSteps": "Total de passos", + "bestDay": "Melhor dia", + "steps": "passos", + "rewards": "Enviar recompensas", + "rewardsMessage": "*Usando esta função podes recompensar o teu filho por metas alcançadas ou boas ações.", + "sendRewards": "Enviar recompensas!", + "rewardsSent": "Recompensas enviadas!", + "appsUse": "Uso das aplicações", + "topApps": "Apps mais usadas", + "noAppUsageData": "Sem dados de uso de aplicações", + "selectDay": "Seleção de dias", + "alarmMessage": "Mensagem", + "alarmMessageHint": "Texto que o alarme exibirá", + "deleteAlarm": "Eliminar alarme", + "deleteAlarmConfirm": "Tem certeza de que deseja eliminar este alarme?", + "editAlarm": "Editar alarme", + "noAlarms": "Nenhum alarme configurado", + "alarmCreated": "Alarme criado com sucesso", + "alarmUpdated": "Alarme atualizado com sucesso", + "alarmDeleted": "Alarme eliminado com sucesso", + "noActivityData": "Sem medições de atividade para exibir", + "phone": "Telefone", + "add": "Adicionar", + "contactName": "Nome do contato", + "addAllowedNumber": "Adicionar número permitido", + "noBlockedNumbers": "Nenhum número configurado", + "noBlockedNumbersDescription": "Adicione números para restringir quem pode comunicar com o dispositivo", + "whitelistDescription": "Apenas estes números podem comunicar com o dispositivo", + "allowedNumbersCount": "{count} números permitidos", + "removeAllowedNumber": "Remover número permitido", + "removeAllowedNumberConfirm": "Remover \"{name}\" da lista de números permitidos? Este número não poderá mais comunicar com o dispositivo", + "numberAdded": "Número adicionado com sucesso", + "numberRemoved": "Número removido com sucesso", + "addSosContact": "Adicionar contacto SOS", + "noSosContacts": "Nenhum contacto SOS configurado", + "noSosContactsDescription": "Adicione contactos de emergência que o dispositivo pode ligar em caso de emergência", + "sosDescription": "Estes contactos estarão disponíveis para chamadas de emergência a partir do dispositivo", + "sosContactsCount": "{count} contactos SOS", + "removeSosContact": "Remover contacto SOS", + "removeSosContactConfirm": "Remover \"{name}\" da lista de contactos SOS? Este contacto deixará de estar disponível para chamadas de emergência", + "sosNumberAdded": "Contacto SOS adicionado com sucesso", + "sosNumberRemoved": "Contacto SOS removido com sucesso", + "addWifiNetwork": "Adicionar rede WiFi", + "noWifiNetworks": "Nenhuma rede WiFi configurada", + "noWifiNetworksDescription": "Adicione redes WiFi às quais o dispositivo pode conectar-se automaticamente", + "wifiDescription": "O dispositivo conectar-se-á automaticamente a estas redes WiFi quando estiver ao alcance", + "wifiNetworksCount": "{count} redes WiFi", + "removeWifiNetwork": "Remover rede WiFi", + "removeWifiNetworkConfirm": "Remover \"{name}\" da lista de redes WiFi? O dispositivo deixará de se conectar automaticamente a esta rede", + "wifiNetworkAdded": "Rede WiFi adicionada com sucesso", + "wifiNetworkRemoved": "Rede WiFi removida com sucesso", + "wifiSsid": "Nome da rede (SSID)", + "wifiBssid": "Endereço MAC (BSSID)", + "wifiSsidHint": "ex. MinhaRedeWiFi", + "wifiBssidHint": "ex. 0c:80:63:e4:cb:e1" } \ No newline at end of file diff --git a/packages/sf_localizations/lib/src/generated/i18n.dart b/packages/sf_localizations/lib/src/generated/i18n.dart index 836f9f8c..7b459e99 100755 --- a/packages/sf_localizations/lib/src/generated/i18n.dart +++ b/packages/sf_localizations/lib/src/generated/i18n.dart @@ -635,10 +635,31 @@ class I18n { static const String doNotDisturb = 'doNotDisturb'; static const String videoCall = 'videoCall'; static const String health = 'health'; + static const String healthEmpty = 'healthEmpty'; + static const String healthEmptyHint = 'healthEmptyHint'; + static const String heartRate = 'heartRate'; + static const String bloodPressure = 'bloodPressure'; + static const String oxygenLevel = 'oxygenLevel'; + static const String bpm = 'bpm'; + static const String mmHg = 'mmHg'; + static const String spo2 = 'spo2'; + static const String noData = 'noData'; + static const String today = 'today'; + static const String yesterday = 'yesterday'; + static const String lastReading = 'lastReading'; + static const String timeAgo = 'timeAgo'; + static const String sevenDays = 'sevenDays'; + static const String thirtyDays = 'thirtyDays'; + static const String custom = 'custom'; + static const String average = 'average'; + static const String minimum = 'minimum'; + static const String maximum = 'maximum'; + static const String history = 'history'; static const String activityMeter = 'activityMeter'; static const String rewards = 'rewards'; static const String callWatch = 'callWatch'; static const String appsUse = 'appsUse'; + static const String topApps = 'topApps'; static const String appsSurveillance = 'appsSurveillance'; static const String makeFriends = 'makeFriends'; static const String locateSF = 'locateSF'; @@ -663,6 +684,7 @@ class I18n { static const String activationKeyLabel = 'activationKeyLabel'; static const String rewardsMessage = 'rewardsMessage'; static const String sendRewards = 'sendRewards'; + static const String rewardsSent = 'rewardsSent'; static const String male = 'male'; static const String female = 'female'; static const String ratherNotSay = 'ratherNotSay'; @@ -676,6 +698,15 @@ class I18n { static const String once = 'once'; static const String daily = 'daily'; static const String selectDay = 'selectDay'; + static const String alarmMessage = 'alarmMessage'; + static const String alarmMessageHint = 'alarmMessageHint'; + static const String deleteAlarm = 'deleteAlarm'; + static const String deleteAlarmConfirm = 'deleteAlarmConfirm'; + static const String editAlarm = 'editAlarm'; + static const String noAlarms = 'noAlarms'; + static const String alarmCreated = 'alarmCreated'; + static const String alarmUpdated = 'alarmUpdated'; + static const String alarmDeleted = 'alarmDeleted'; static const String remoteTurnOff = 'remoteTurnOff'; static const String remoteTurnOffMessage = 'remoteTurnOffMessage'; static const String remoteTurnOffConfirm = 'remoteTurnOffConfirm'; @@ -707,4 +738,73 @@ class I18n { static const String remoteOnOff = 'remoteOnOff'; static const String disableFunctions = 'disableFunctions'; static const String syncClock = 'syncClock'; + static const String monday = 'monday'; + static const String tuesday = 'tuesday'; + static const String wednesday = 'wednesday'; + static const String thursday = 'thursday'; + static const String friday = 'friday'; + static const String saturday = 'saturday'; + static const String sunday = 'sunday'; + static const String scheduledActivityEmpty = 'scheduledActivityEmpty'; + static const String scheduledActivityEmptyHint = 'scheduledActivityEmptyHint'; + static const String scheduledActivityStartTime = 'scheduledActivityStartTime'; + static const String scheduledActivityEndTime = 'scheduledActivityEndTime'; + static const String scheduledActivityStartBeforeEnd = 'scheduledActivityStartBeforeEnd'; + static const String scheduledActivityOverlap = 'scheduledActivityOverlap'; + static const String scheduledActivityNewTitle = 'scheduledActivityNewTitle'; + static const String scheduledActivityEditTitle = 'scheduledActivityEditTitle'; + static const String scheduledActivityDeleteTitle = 'scheduledActivityDeleteTitle'; + static const String scheduledActivityDeleteMessage = 'scheduledActivityDeleteMessage'; + static const String mainContactPhoneNumber = 'mainContactPhoneNumber'; + static const String loadingPhoto = 'loadingPhoto'; + static const String editContact = 'editContact'; + static const String sending = 'sending'; + static const String sentSuccessfully = 'sentSuccessfully'; + static const String deviceNotConnected = 'deviceNotConnected'; + static const String ok = 'ok'; + static const String locateDeviceConfirmMessage = 'locateDeviceConfirmMessage'; + static const String continueWithGoogle = 'continueWithGoogle'; + static const String redirectingToGoogle = 'redirectingToGoogle'; + static const String errorMessagePhoneIsInvalid = 'errorMessagePhoneIsInvalid'; + static const String contactsEmpty = 'contactsEmpty'; + static const String contactsEmptyHint = 'contactsEmptyHint'; + static const String totalSteps = 'totalSteps'; + static const String bestDay = 'bestDay'; + static const String steps = 'steps'; + static const String noAppUsageData = 'noAppUsageData'; + static const String noActivityData = 'noActivityData'; + static const String phone = 'phone'; + static const String add = 'add'; + static const String contactName = 'contactName'; + static const String addAllowedNumber = 'addAllowedNumber'; + static const String noBlockedNumbers = 'noBlockedNumbers'; + static const String noBlockedNumbersDescription = 'noBlockedNumbersDescription'; + static const String whitelistDescription = 'whitelistDescription'; + static const String allowedNumbersCount = 'allowedNumbersCount'; + static const String removeAllowedNumber = 'removeAllowedNumber'; + static const String removeAllowedNumberConfirm = 'removeAllowedNumberConfirm'; + static const String numberAdded = 'numberAdded'; + static const String numberRemoved = 'numberRemoved'; + static const String addSosContact = 'addSosContact'; + static const String noSosContacts = 'noSosContacts'; + static const String noSosContactsDescription = 'noSosContactsDescription'; + static const String sosDescription = 'sosDescription'; + static const String sosContactsCount = 'sosContactsCount'; + static const String removeSosContact = 'removeSosContact'; + static const String removeSosContactConfirm = 'removeSosContactConfirm'; + static const String sosNumberAdded = 'sosNumberAdded'; + static const String sosNumberRemoved = 'sosNumberRemoved'; + static const String addWifiNetwork = 'addWifiNetwork'; + static const String noWifiNetworks = 'noWifiNetworks'; + static const String noWifiNetworksDescription = 'noWifiNetworksDescription'; + static const String wifiDescription = 'wifiDescription'; + static const String wifiNetworksCount = 'wifiNetworksCount'; + static const String removeWifiNetwork = 'removeWifiNetwork'; + static const String removeWifiNetworkConfirm = 'removeWifiNetworkConfirm'; + static const String wifiNetworkAdded = 'wifiNetworkAdded'; + static const String wifiNetworkRemoved = 'wifiNetworkRemoved'; + static const String wifiSsid = 'wifiSsid'; + static const String wifiBssid = 'wifiBssid'; + static const String wifiSsidHint = 'wifiSsidHint'; + static const String wifiBssidHint = 'wifiBssidHint'; } diff --git a/packages/sf_shared/lib/src/providers/user_info_provider.dart b/packages/sf_shared/lib/src/providers/user_info_provider.dart index cfe06e48..192306ad 100644 --- a/packages/sf_shared/lib/src/providers/user_info_provider.dart +++ b/packages/sf_shared/lib/src/providers/user_info_provider.dart @@ -2,7 +2,16 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:sf_shared/sf_shared.dart'; final userInfoProvider = - FutureProvider.autoDispose((ref) async { - final getUserInfoUseCase = ref.read(getUserInfoUseCaseProvider); - return getUserInfoUseCase.getUserInfo(); -}); + AsyncNotifierProvider(UserInfoNotifier.new); + +class UserInfoNotifier extends AsyncNotifier { + @override + Future build() async { + final getUserInfoUseCase = ref.read(getUserInfoUseCaseProvider); + return getUserInfoUseCase.getUserInfo(); + } + + void setUser(UserEntity user) { + state = AsyncData(user); + } +}