Compare commits
18 Commits
fonts
...
onboarding
| Author | SHA1 | Date | |
|---|---|---|---|
| ae429302bb | |||
| 1f3de3df26 | |||
| bbe77f6a8a | |||
|
|
760e94ffe9 | ||
|
|
ad10ad3b59 | ||
| baef98a443 | |||
| b8bb3e65c2 | |||
| cbc991b2fd | |||
|
|
6b3776f618 | ||
| 7bfc4039ab | |||
| 16e3c68d1a | |||
| 4869850c43 | |||
| cb7ff71756 | |||
| 99f544e24c | |||
|
|
07a0fd5695 | ||
|
|
b823b422f0 | ||
|
|
a64a9a2a32 | ||
|
|
9d7f940851 |
364
.dart_tool/package_config.json
Normal file
@@ -0,0 +1,364 @@
|
|||||||
|
{
|
||||||
|
"configVersion": 2,
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "ansi_styles",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/ansi_styles-0.3.2+1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "args",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/args-2.7.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "async",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/async-2.13.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "characters",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/characters-1.4.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "charcode",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/charcode-1.4.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "checked_yaml",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/checked_yaml-2.0.4",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cli_launcher",
|
||||||
|
"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:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cli_util-0.4.2",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "collection",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/collection-1.19.1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "conventional_commit",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/conventional_commit-0.6.1+1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ffi",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/ffi-2.1.4",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "file",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/file-7.0.1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter_secure_storage",
|
||||||
|
"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:///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:///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:///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:///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:///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:///Users/juliandalcalaf/Development/flutter/packages/flutter_web_plugins",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "glob",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/glob-2.1.3",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "graphs",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/graphs-2.3.2",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http-1.5.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http_parser",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http_parser-4.1.2",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "io",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/io-1.0.5",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "js",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/js-0.6.7",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "json_annotation",
|
||||||
|
"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:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "melos",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/melos-6.3.3",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "meta",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/meta-1.16.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mustache_template",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/mustache_template-2.0.2",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "path",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path-1.9.1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "path_provider",
|
||||||
|
"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:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_android-2.2.20",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "path_provider_foundation",
|
||||||
|
"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:///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:///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:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "platform",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/platform-3.1.6",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "plugin_platform_interface",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pool",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pool-1.5.2",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "process",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/process-5.0.5",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "prompts",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/prompts-2.0.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pub_semver",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pub_semver-2.2.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pub_updater",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pub_updater-0.5.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pubspec_parse",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pubspec_parse-1.5.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sky_engine",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/Development/flutter/bin/cache/pkg/sky_engine",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "source_span",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_span-1.10.1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stack_trace",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stack_trace-1.12.1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "string_scanner",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/string_scanner-1.4.1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "term_glyph",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/term_glyph-1.2.2",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "typed_data",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/typed_data-1.4.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "vector_math",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_math-2.2.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "web",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web-1.1.1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "win32",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/win32-5.15.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "xdg_directories",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "yaml",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/yaml-3.1.3",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "yaml_edit",
|
||||||
|
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/yaml_edit-2.2.2",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sf_app_platform_mono_repo",
|
||||||
|
"rootUri": "../",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"generator": "pub",
|
||||||
|
"generatorVersion": "3.9.2",
|
||||||
|
"flutterRoot": "file:///Users/juliandalcalaf/Development/flutter",
|
||||||
|
"flutterVersion": "3.35.7",
|
||||||
|
"pubCache": "file:///Users/juliandalcalaf/.pub-cache"
|
||||||
|
}
|
||||||
491
.dart_tool/package_graph.json
Normal file
@@ -0,0 +1,491 @@
|
|||||||
|
{
|
||||||
|
"roots": [
|
||||||
|
"sf_app_platform_mono_repo"
|
||||||
|
],
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "sf_app_platform_mono_repo",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": [
|
||||||
|
"flutter_secure_storage"
|
||||||
|
],
|
||||||
|
"devDependencies": [
|
||||||
|
"melos"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter_secure_storage",
|
||||||
|
"version": "9.2.4",
|
||||||
|
"dependencies": [
|
||||||
|
"flutter",
|
||||||
|
"flutter_secure_storage_linux",
|
||||||
|
"flutter_secure_storage_macos",
|
||||||
|
"flutter_secure_storage_platform_interface",
|
||||||
|
"flutter_secure_storage_web",
|
||||||
|
"flutter_secure_storage_windows",
|
||||||
|
"meta"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "melos",
|
||||||
|
"version": "6.3.3",
|
||||||
|
"dependencies": [
|
||||||
|
"ansi_styles",
|
||||||
|
"args",
|
||||||
|
"async",
|
||||||
|
"cli_launcher",
|
||||||
|
"cli_util",
|
||||||
|
"collection",
|
||||||
|
"conventional_commit",
|
||||||
|
"file",
|
||||||
|
"glob",
|
||||||
|
"graphs",
|
||||||
|
"http",
|
||||||
|
"meta",
|
||||||
|
"mustache_template",
|
||||||
|
"path",
|
||||||
|
"platform",
|
||||||
|
"pool",
|
||||||
|
"prompts",
|
||||||
|
"pub_semver",
|
||||||
|
"pub_updater",
|
||||||
|
"pubspec_parse",
|
||||||
|
"string_scanner",
|
||||||
|
"yaml",
|
||||||
|
"yaml_edit"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "meta",
|
||||||
|
"version": "1.16.0",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter_secure_storage_windows",
|
||||||
|
"version": "3.1.2",
|
||||||
|
"dependencies": [
|
||||||
|
"ffi",
|
||||||
|
"flutter",
|
||||||
|
"flutter_secure_storage_platform_interface",
|
||||||
|
"path",
|
||||||
|
"path_provider",
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter_secure_storage_web",
|
||||||
|
"version": "1.2.1",
|
||||||
|
"dependencies": [
|
||||||
|
"flutter",
|
||||||
|
"flutter_secure_storage_platform_interface",
|
||||||
|
"flutter_web_plugins",
|
||||||
|
"js"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter_secure_storage_platform_interface",
|
||||||
|
"version": "1.1.2",
|
||||||
|
"dependencies": [
|
||||||
|
"flutter",
|
||||||
|
"plugin_platform_interface"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter_secure_storage_macos",
|
||||||
|
"version": "3.1.3",
|
||||||
|
"dependencies": [
|
||||||
|
"flutter",
|
||||||
|
"flutter_secure_storage_platform_interface"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter_secure_storage_linux",
|
||||||
|
"version": "1.2.3",
|
||||||
|
"dependencies": [
|
||||||
|
"flutter",
|
||||||
|
"flutter_secure_storage_platform_interface"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": [
|
||||||
|
"characters",
|
||||||
|
"collection",
|
||||||
|
"material_color_utilities",
|
||||||
|
"meta",
|
||||||
|
"sky_engine",
|
||||||
|
"vector_math"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "yaml_edit",
|
||||||
|
"version": "2.2.2",
|
||||||
|
"dependencies": [
|
||||||
|
"collection",
|
||||||
|
"meta",
|
||||||
|
"source_span",
|
||||||
|
"yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "yaml",
|
||||||
|
"version": "3.1.3",
|
||||||
|
"dependencies": [
|
||||||
|
"collection",
|
||||||
|
"source_span",
|
||||||
|
"string_scanner"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "string_scanner",
|
||||||
|
"version": "1.4.1",
|
||||||
|
"dependencies": [
|
||||||
|
"source_span"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pubspec_parse",
|
||||||
|
"version": "1.5.0",
|
||||||
|
"dependencies": [
|
||||||
|
"checked_yaml",
|
||||||
|
"collection",
|
||||||
|
"json_annotation",
|
||||||
|
"pub_semver",
|
||||||
|
"yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pub_updater",
|
||||||
|
"version": "0.5.0",
|
||||||
|
"dependencies": [
|
||||||
|
"http",
|
||||||
|
"json_annotation",
|
||||||
|
"process",
|
||||||
|
"pub_semver"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pub_semver",
|
||||||
|
"version": "2.2.0",
|
||||||
|
"dependencies": [
|
||||||
|
"collection"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "prompts",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"dependencies": [
|
||||||
|
"charcode",
|
||||||
|
"io"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pool",
|
||||||
|
"version": "1.5.2",
|
||||||
|
"dependencies": [
|
||||||
|
"async",
|
||||||
|
"stack_trace"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "platform",
|
||||||
|
"version": "3.1.6",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "path",
|
||||||
|
"version": "1.9.1",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mustache_template",
|
||||||
|
"version": "2.0.2",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http",
|
||||||
|
"version": "1.5.0",
|
||||||
|
"dependencies": [
|
||||||
|
"async",
|
||||||
|
"http_parser",
|
||||||
|
"meta",
|
||||||
|
"web"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "graphs",
|
||||||
|
"version": "2.3.2",
|
||||||
|
"dependencies": [
|
||||||
|
"collection"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "glob",
|
||||||
|
"version": "2.1.3",
|
||||||
|
"dependencies": [
|
||||||
|
"async",
|
||||||
|
"collection",
|
||||||
|
"file",
|
||||||
|
"path",
|
||||||
|
"string_scanner"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "file",
|
||||||
|
"version": "7.0.1",
|
||||||
|
"dependencies": [
|
||||||
|
"meta",
|
||||||
|
"path"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "conventional_commit",
|
||||||
|
"version": "0.6.1+1",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "collection",
|
||||||
|
"version": "1.19.1",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cli_util",
|
||||||
|
"version": "0.4.2",
|
||||||
|
"dependencies": [
|
||||||
|
"meta",
|
||||||
|
"path"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cli_launcher",
|
||||||
|
"version": "0.3.2+1",
|
||||||
|
"dependencies": [
|
||||||
|
"path",
|
||||||
|
"yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "async",
|
||||||
|
"version": "2.13.0",
|
||||||
|
"dependencies": [
|
||||||
|
"collection",
|
||||||
|
"meta"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "args",
|
||||||
|
"version": "2.7.0",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ansi_styles",
|
||||||
|
"version": "0.3.2+1",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "win32",
|
||||||
|
"version": "5.15.0",
|
||||||
|
"dependencies": [
|
||||||
|
"ffi"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "path_provider",
|
||||||
|
"version": "2.1.5",
|
||||||
|
"dependencies": [
|
||||||
|
"flutter",
|
||||||
|
"path_provider_android",
|
||||||
|
"path_provider_foundation",
|
||||||
|
"path_provider_linux",
|
||||||
|
"path_provider_platform_interface",
|
||||||
|
"path_provider_windows"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ffi",
|
||||||
|
"version": "2.1.4",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "js",
|
||||||
|
"version": "0.6.7",
|
||||||
|
"dependencies": [
|
||||||
|
"meta"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter_web_plugins",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": [
|
||||||
|
"flutter"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "plugin_platform_interface",
|
||||||
|
"version": "2.1.8",
|
||||||
|
"dependencies": [
|
||||||
|
"meta"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sky_engine",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "vector_math",
|
||||||
|
"version": "2.2.0",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "material_color_utilities",
|
||||||
|
"version": "0.11.1",
|
||||||
|
"dependencies": [
|
||||||
|
"collection"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "characters",
|
||||||
|
"version": "1.4.0",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "source_span",
|
||||||
|
"version": "1.10.1",
|
||||||
|
"dependencies": [
|
||||||
|
"collection",
|
||||||
|
"path",
|
||||||
|
"term_glyph"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "json_annotation",
|
||||||
|
"version": "4.9.0",
|
||||||
|
"dependencies": [
|
||||||
|
"meta"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "checked_yaml",
|
||||||
|
"version": "2.0.4",
|
||||||
|
"dependencies": [
|
||||||
|
"json_annotation",
|
||||||
|
"source_span",
|
||||||
|
"yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "process",
|
||||||
|
"version": "5.0.5",
|
||||||
|
"dependencies": [
|
||||||
|
"file",
|
||||||
|
"path",
|
||||||
|
"platform"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "io",
|
||||||
|
"version": "1.0.5",
|
||||||
|
"dependencies": [
|
||||||
|
"meta",
|
||||||
|
"path",
|
||||||
|
"string_scanner"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "charcode",
|
||||||
|
"version": "1.4.0",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stack_trace",
|
||||||
|
"version": "1.12.1",
|
||||||
|
"dependencies": [
|
||||||
|
"path"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "web",
|
||||||
|
"version": "1.1.1",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http_parser",
|
||||||
|
"version": "4.1.2",
|
||||||
|
"dependencies": [
|
||||||
|
"collection",
|
||||||
|
"source_span",
|
||||||
|
"string_scanner",
|
||||||
|
"typed_data"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "path_provider_windows",
|
||||||
|
"version": "2.3.0",
|
||||||
|
"dependencies": [
|
||||||
|
"ffi",
|
||||||
|
"flutter",
|
||||||
|
"path",
|
||||||
|
"path_provider_platform_interface"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "path_provider_platform_interface",
|
||||||
|
"version": "2.1.2",
|
||||||
|
"dependencies": [
|
||||||
|
"flutter",
|
||||||
|
"platform",
|
||||||
|
"plugin_platform_interface"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "path_provider_linux",
|
||||||
|
"version": "2.2.1",
|
||||||
|
"dependencies": [
|
||||||
|
"ffi",
|
||||||
|
"flutter",
|
||||||
|
"path",
|
||||||
|
"path_provider_platform_interface",
|
||||||
|
"xdg_directories"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "path_provider_foundation",
|
||||||
|
"version": "2.4.3",
|
||||||
|
"dependencies": [
|
||||||
|
"flutter",
|
||||||
|
"path_provider_platform_interface"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "path_provider_android",
|
||||||
|
"version": "2.2.20",
|
||||||
|
"dependencies": [
|
||||||
|
"flutter",
|
||||||
|
"path_provider_platform_interface"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "term_glyph",
|
||||||
|
"version": "1.2.2",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "typed_data",
|
||||||
|
"version": "1.4.0",
|
||||||
|
"dependencies": [
|
||||||
|
"collection"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "xdg_directories",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"dependencies": [
|
||||||
|
"meta",
|
||||||
|
"path"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configVersion": 1
|
||||||
|
}
|
||||||
BIN
.dart_tool/pub/bin/melos/melos.dart-3.9.2.snapshot
Normal file
1
.dart_tool/version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.35.7
|
||||||
1
.flutter-plugins-dependencies
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"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":"2025-12-04 12:33:12.174628","version":"3.35.7","swift_package_manager_enabled":{"ios":false,"macos":false}}
|
||||||
1
.idea/modules.xml
generated
@@ -11,6 +11,7 @@
|
|||||||
<module fileurl="file://$PROJECT_DIR$/modules/notifications/melos_notifications.iml" filepath="$PROJECT_DIR$/modules/notifications/melos_notifications.iml" />
|
<module fileurl="file://$PROJECT_DIR$/modules/notifications/melos_notifications.iml" filepath="$PROJECT_DIR$/modules/notifications/melos_notifications.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/modules/profile/melos_profile.iml" filepath="$PROJECT_DIR$/modules/profile/melos_profile.iml" />
|
<module fileurl="file://$PROJECT_DIR$/modules/profile/melos_profile.iml" filepath="$PROJECT_DIR$/modules/profile/melos_profile.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/apps/mobile_app/melos_sf_app_platform.iml" filepath="$PROJECT_DIR$/apps/mobile_app/melos_sf_app_platform.iml" />
|
<module fileurl="file://$PROJECT_DIR$/apps/mobile_app/melos_sf_app_platform.iml" filepath="$PROJECT_DIR$/apps/mobile_app/melos_sf_app_platform.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/sf_infrastructure/melos_sf_infrastructure.iml" filepath="$PROJECT_DIR$/packages/sf_infrastructure/melos_sf_infrastructure.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/packages/sf_localizations/melos_sf_localizations.iml" filepath="$PROJECT_DIR$/packages/sf_localizations/melos_sf_localizations.iml" />
|
<module fileurl="file://$PROJECT_DIR$/packages/sf_localizations/melos_sf_localizations.iml" filepath="$PROJECT_DIR$/packages/sf_localizations/melos_sf_localizations.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/packages/sf_shared/melos_sf_shared.iml" filepath="$PROJECT_DIR$/packages/sf_shared/melos_sf_shared.iml" />
|
<module fileurl="file://$PROJECT_DIR$/packages/sf_shared/melos_sf_shared.iml" filepath="$PROJECT_DIR$/packages/sf_shared/melos_sf_shared.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/packages/utils/melos_utils.iml" filepath="$PROJECT_DIR$/packages/utils/melos_utils.iml" />
|
<module fileurl="file://$PROJECT_DIR$/packages/utils/melos_utils.iml" filepath="$PROJECT_DIR$/packages/utils/melos_utils.iml" />
|
||||||
|
|||||||
7
.idea/runConfigurations/melos_flutter_test_sf_infrastructure.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<!-- Generated by Melos -->
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Flutter Test -> 'sf_infrastructure'" type="FlutterTestConfigType" factoryName="Flutter Test">
|
||||||
|
<option name="testDir" value="$PROJECT_DIR$/packages/sf_infrastructure/test" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
1
apps/mobile_app/.env
Normal file
@@ -0,0 +1 @@
|
|||||||
|
API_BASE_URL=https://api-neki-b2b.neki.es/gateway/api/
|
||||||
7
apps/mobile_app/lib/config/env/env.dart
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
|
|
||||||
|
class Env {
|
||||||
|
static String get apiBaseUrl => dotenv.env['API_BASE_URL'] ?? '';
|
||||||
|
|
||||||
|
// static String get apiKey => dotenv.env['API_KEY'] ?? '';
|
||||||
|
}
|
||||||
10
apps/mobile_app/lib/config/env/questia_env_config.dart
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||||
|
import 'env.dart';
|
||||||
|
|
||||||
|
class QuestiaEnvConfig implements EnvConfig {
|
||||||
|
@override
|
||||||
|
String get apiBaseUrl => Env.apiBaseUrl;
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// String get apiKey => Env.apiKey;
|
||||||
|
}
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
|
import 'package:sf_app_platform/config/env/questia_env_config.dart';
|
||||||
import 'package:sf_app_platform/navigation/app_router.dart';
|
import 'package:sf_app_platform/navigation/app_router.dart';
|
||||||
import 'package:navigation/navigation_module.dart';
|
import 'package:navigation/navigation_module.dart';
|
||||||
|
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||||
import 'package:sf_localizations/sf_localizations.dart';
|
import 'package:sf_localizations/sf_localizations.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
@@ -11,7 +15,9 @@ Future<void> main() async {
|
|||||||
navigationModule();
|
navigationModule();
|
||||||
configureAppRouter();
|
configureAppRouter();
|
||||||
themePackages();
|
themePackages();
|
||||||
|
await dotenv.load(fileName: '.env');
|
||||||
|
|
||||||
|
await configureDependencies(QuestiaEnvConfig(), log: kDebugMode);
|
||||||
runApp(const ProviderScope(child: PlatformApp()));
|
runApp(const ProviderScope(child: PlatformApp()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,4 +54,4 @@ class PlatformApp extends ConsumerWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ late final GoRouter appRouter;
|
|||||||
void configureAppRouter() {
|
void configureAppRouter() {
|
||||||
appRouter = GoRouter(
|
appRouter = GoRouter(
|
||||||
navigatorKey: rootNavigatorKey,
|
navigatorKey: rootNavigatorKey,
|
||||||
initialLocation: AppRoutes.onboarding,
|
initialLocation: AppRoutes.linkPhone,
|
||||||
debugLogDiagnostics: true,
|
debugLogDiagnostics: true,
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
|
|||||||
@@ -168,6 +168,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
|
country_code_picker:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: country_code_picker
|
||||||
|
sha256: f0411f4833b6f98e8b7215f4fa3813bcc88e50f13925f70a170dbd36e3e447f5
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.4.1"
|
||||||
coverage:
|
coverage:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -214,6 +222,30 @@ packages:
|
|||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "0.0.1"
|
version: "0.0.1"
|
||||||
|
diacritic:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: diacritic
|
||||||
|
sha256: "12981945ec38931748836cd76f2b38773118d0baef3c68404bdfde9566147876"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.6"
|
||||||
|
dio:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dio
|
||||||
|
sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.9.0"
|
||||||
|
dio_web_adapter:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dio_web_adapter
|
||||||
|
sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
equatable:
|
equatable:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -259,6 +291,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_dotenv:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_dotenv
|
||||||
|
sha256: d4130c4a43e0b13fefc593bc3961f2cb46e30cb79e253d4a526b1b5d24ae1ce4
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.0"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@@ -408,6 +448,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.20.2"
|
version: "0.20.2"
|
||||||
|
intl_phone_field_v2:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: intl_phone_field_v2
|
||||||
|
sha256: b1e5077e31cc8705639a69b2e0410a8ecc858c3e518726d99b378b6c35adfefb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.5"
|
||||||
io:
|
io:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -597,6 +645,13 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.3"
|
||||||
|
sf_infrastructure:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "../../packages/sf_infrastructure"
|
||||||
|
relative: true
|
||||||
|
source: path
|
||||||
|
version: "0.0.1"
|
||||||
sf_localizations:
|
sf_localizations:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -57,12 +57,15 @@ dependencies:
|
|||||||
path: ../../packages/sf_localizations
|
path: ../../packages/sf_localizations
|
||||||
fonts:
|
fonts:
|
||||||
path: ../../packages/fonts
|
path: ../../packages/fonts
|
||||||
|
sf_infrastructure:
|
||||||
|
path: ../../packages/sf_infrastructure
|
||||||
|
|
||||||
#dependencies go here
|
#dependencies go here
|
||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
flutter_svg: ^2.2.1
|
flutter_svg: ^2.2.1
|
||||||
go_router_builder: ^4.1.1
|
go_router_builder: ^4.1.1
|
||||||
build_runner: ^2.7.1
|
build_runner: ^2.7.1
|
||||||
|
flutter_dotenv: ^6.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -89,7 +92,7 @@ flutter:
|
|||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
assets:
|
assets:
|
||||||
- assets/images/ui/
|
- assets/images/ui/
|
||||||
|
- .env
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
# https://flutter.dev/to/resolution-aware-images
|
# https://flutter.dev/to/resolution-aware-images
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# melos_managed_dependency_overrides: auth,dashboard_shell,design_system,home,navigation,notifications,profile,sf_shared,utils,sf_localizations,fonts
|
# melos_managed_dependency_overrides: auth,dashboard_shell,design_system,home,navigation,notifications,profile,sf_shared,utils,sf_localizations,fonts,sf_infrastructure
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
auth:
|
auth:
|
||||||
path: ../../modules/auth
|
path: ../../modules/auth
|
||||||
@@ -16,6 +16,8 @@ dependency_overrides:
|
|||||||
path: ../../modules/notifications
|
path: ../../modules/notifications
|
||||||
profile:
|
profile:
|
||||||
path: ../../modules/profile
|
path: ../../modules/profile
|
||||||
|
sf_infrastructure:
|
||||||
|
path: ../../packages/sf_infrastructure
|
||||||
sf_localizations:
|
sf_localizations:
|
||||||
path: ../../packages/sf_localizations
|
path: ../../packages/sf_localizations
|
||||||
sf_shared:
|
sf_shared:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
export 'src/device_sign_up/link_watch/create_profile_screen.dart';
|
export 'src/features/device_sign_up/link_watch/create_profile_screen.dart';
|
||||||
export 'src/onboarding/onboarding_builder.dart';
|
export 'src/features/onboarding/onboarding_builder.dart';
|
||||||
export 'src/login/link_phone_builder.dart';
|
export 'src/features/link_phone/link_phone_builder.dart';
|
||||||
export 'src/login/phone_code_builder.dart';
|
export 'src/features/login/phone_code_builder.dart';
|
||||||
export 'src/login/login_builder.dart';
|
export 'src/features/login/login_builder.dart';
|
||||||
export 'src/recover_password/recover_password_builder.dart';
|
export 'src/features/recover_password/recover_password_builder.dart';
|
||||||
export 'src/device_sign_up/device_signup_builder.dart';
|
export 'src/features/device_sign_up/device_signup_builder.dart';
|
||||||
export 'src/sign_up/signup_builder.dart';
|
export 'src/features/sign_up/signup_builder.dart';
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
abstract class AuthRemoteDatasource {
|
||||||
|
Future<void> requestPhoneCode({required String phone});
|
||||||
|
|
||||||
|
Future<void> verifyPhoneCode({required String phone, required String code});
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||||
|
|
||||||
|
import 'auth_remote_datasource.dart';
|
||||||
|
|
||||||
|
class AuthRemoteDatasourceImpl implements AuthRemoteDatasource {
|
||||||
|
AuthRemoteDatasourceImpl(this._repository);
|
||||||
|
|
||||||
|
final QuestiaRepository _repository;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> requestPhoneCode({required String phone}) async {
|
||||||
|
try {
|
||||||
|
await _repository.post<void>(
|
||||||
|
'/auth/link-phone/request-code',
|
||||||
|
body: <String, dynamic>{'phone': phone},
|
||||||
|
);
|
||||||
|
} on DioException catch (error) {
|
||||||
|
throw _mapDioError(error, defaultMessage: 'Error al solicitar el código');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> verifyPhoneCode({
|
||||||
|
required String phone,
|
||||||
|
required String code,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
await _repository.post<void>(
|
||||||
|
'/auth/link-phone/verify-code',
|
||||||
|
body: <String, dynamic>{'phone': phone, 'code': code},
|
||||||
|
);
|
||||||
|
} on DioException catch (error) {
|
||||||
|
throw _mapDioError(error, defaultMessage: 'Error al verificar el código');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Exception _mapDioError(DioException error, {required String defaultMessage}) {
|
||||||
|
final responseData = error.response?.data;
|
||||||
|
String message = defaultMessage;
|
||||||
|
|
||||||
|
if (responseData is Map<String, dynamic>) {
|
||||||
|
final serverMessage = responseData['message'];
|
||||||
|
if (serverMessage is String && serverMessage.isNotEmpty) {
|
||||||
|
message = serverMessage;
|
||||||
|
}
|
||||||
|
} else if (error.message != null && error.message!.isNotEmpty) {
|
||||||
|
message = error.message!;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Exception(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import 'package:auth/src/core/data/datasource/auth_remote_datasource.dart';
|
||||||
|
import 'package:auth/src/core/domain/repositories/auth_repository.dart';
|
||||||
|
|
||||||
|
class AuthRepositoryImpl implements AuthRepository {
|
||||||
|
const AuthRepositoryImpl(this._remote);
|
||||||
|
|
||||||
|
final AuthRemoteDatasource _remote;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> requestPhoneCode({required String phone}) {
|
||||||
|
return _remote.requestPhoneCode(phone: phone);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> verifyPhoneCode({required String phone, required String code}) {
|
||||||
|
return _remote.verifyPhoneCode(phone: phone, code: code);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
abstract class AuthRepository {
|
||||||
|
Future<void> requestPhoneCode({required String phone});
|
||||||
|
|
||||||
|
Future<void> verifyPhoneCode({required String phone, required String code});
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import 'package:auth/src/core/data/datasource/auth_remote_datasource.dart';
|
||||||
|
import 'package:auth/src/core/data/datasource/auth_remote_datasource_impl.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||||
|
|
||||||
|
final authRemoteDatasourceProvider = Provider<AuthRemoteDatasource>((ref) {
|
||||||
|
final questiaRepository = getIt<QuestiaRepository>();
|
||||||
|
return AuthRemoteDatasourceImpl(questiaRepository);
|
||||||
|
});
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import 'package:auth/src/core/data/repositories/auth_repository_impl.dart';
|
||||||
|
import 'package:auth/src/core/domain/repositories/auth_repository.dart';
|
||||||
|
import 'package:auth/src/core/providers/auth_remote_datasource_provider.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
final authRepositoryProvider = Provider<AuthRepository>((ref) {
|
||||||
|
final remote = ref.read(authRemoteDatasourceProvider);
|
||||||
|
return AuthRepositoryImpl(remote);
|
||||||
|
});
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:auth/src/device_sign_up/device_signup_screen.dart';
|
import 'package:auth/src/features/device_sign_up/device_signup_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
@@ -1,24 +1,25 @@
|
|||||||
import 'package:auth/auth.dart';
|
import 'package:auth/auth.dart';
|
||||||
import 'package:auth/src/device_sign_up/add_kid_screen.dart';
|
import 'package:auth/src/features/device_sign_up/add_kid_screen.dart';
|
||||||
import 'package:auth/src/device_sign_up/link_watch/link_watch_screen.dart';
|
import 'package:auth/src/features/device_sign_up/link_watch/link_watch_screen.dart';
|
||||||
import 'package:auth/src/device_sign_up/link_watch/link_watch_previous_screen.dart';
|
import 'package:auth/src/features/device_sign_up/link_watch/link_watch_previous_screen.dart';
|
||||||
import 'package:auth/src/sign_up/account_created_screen.dart';
|
import 'package:auth/src/features/sign_up/account_created_screen.dart';
|
||||||
import 'package:auth/src/widgets/layouts/form_step_layout.dart';
|
import 'package:auth/src/widgets/layouts/form_step_layout.dart';
|
||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:navigation/navigation.dart';
|
import 'package:navigation/navigation.dart';
|
||||||
|
|
||||||
class DeviceSignupScreen extends ConsumerStatefulWidget{
|
class DeviceSignupScreen extends ConsumerStatefulWidget {
|
||||||
final NavigationContract navigationContract;
|
final NavigationContract navigationContract;
|
||||||
|
|
||||||
const DeviceSignupScreen({super.key, required this.navigationContract});
|
const DeviceSignupScreen({super.key, required this.navigationContract});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<DeviceSignupScreen> createState() => DeviceSignupScreenState(navigationContract);
|
ConsumerState<DeviceSignupScreen> createState() =>
|
||||||
|
DeviceSignupScreenState(navigationContract);
|
||||||
}
|
}
|
||||||
|
|
||||||
class DeviceSignupScreenState extends ConsumerState<DeviceSignupScreen>{
|
class DeviceSignupScreenState extends ConsumerState<DeviceSignupScreen> {
|
||||||
late int currentStep;
|
late int currentStep;
|
||||||
final NavigationContract navigationContract;
|
final NavigationContract navigationContract;
|
||||||
|
|
||||||
@@ -34,37 +35,46 @@ class DeviceSignupScreenState extends ConsumerState<DeviceSignupScreen>{
|
|||||||
return getSteps()[currentStep];
|
return getSteps()[currentStep];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> getSteps(){
|
List<Widget> getSteps() {
|
||||||
final theme = ref.watch(themePortProvider);
|
final theme = ref.watch(themePortProvider);
|
||||||
|
|
||||||
final continueBtn = Container(
|
final continueBtn = Container(
|
||||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||||
child: PrimaryButton(
|
child: PrimaryButton(
|
||||||
onPressed: ()=>{setState(() {
|
onPressed: () => {
|
||||||
currentStep++;
|
setState(() {
|
||||||
})},
|
currentStep++;
|
||||||
|
}),
|
||||||
|
},
|
||||||
text: "Continuar",
|
text: "Continuar",
|
||||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
AddKidScreen(nextStep: ()=>{setState(() {
|
AddKidScreen(
|
||||||
currentStep++;
|
nextStep: () => {
|
||||||
})}),
|
setState(() {
|
||||||
|
currentStep++;
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
),
|
||||||
FormStepLayout(
|
FormStepLayout(
|
||||||
title: "Crea su perfil",
|
title: "Crea su perfil",
|
||||||
subtitle: "Necesitamos estos datos para crear su cuenta y gestionar sus pagos y gastos",
|
subtitle:
|
||||||
|
"Necesitamos estos datos para crear su cuenta y gestionar sus pagos y gastos",
|
||||||
currentStep: 1,
|
currentStep: 1,
|
||||||
numSteps: 3,
|
numSteps: 3,
|
||||||
body: [CreateProfileScreen()],
|
body: [CreateProfileScreen()],
|
||||||
footer: [Container(
|
footer: [
|
||||||
padding: EdgeInsets.all(24),
|
Container(
|
||||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
padding: EdgeInsets.all(24),
|
||||||
child: continueBtn
|
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||||
)],
|
child: continueBtn,
|
||||||
nextStep: ()=>{},
|
),
|
||||||
previousStep: ()=>{}
|
],
|
||||||
|
nextStep: () => {},
|
||||||
|
previousStep: () => {},
|
||||||
),
|
),
|
||||||
FormStepLayout(
|
FormStepLayout(
|
||||||
title: "Vincula su correa y su reloj",
|
title: "Vincula su correa y su reloj",
|
||||||
@@ -72,28 +82,31 @@ class DeviceSignupScreenState extends ConsumerState<DeviceSignupScreen>{
|
|||||||
numSteps: 3,
|
numSteps: 3,
|
||||||
body: [LinkWatchPreviousScreen()],
|
body: [LinkWatchPreviousScreen()],
|
||||||
footer: [continueBtn],
|
footer: [continueBtn],
|
||||||
nextStep: ()=>{},
|
nextStep: () => {},
|
||||||
previousStep: ()=>{}
|
previousStep: () => {},
|
||||||
),
|
),
|
||||||
FormStepLayout(
|
FormStepLayout(
|
||||||
title: "Vincula su correa\ny su reloj",
|
title: "Vincula su correa\ny su reloj",
|
||||||
currentStep: 2,
|
currentStep: 2,
|
||||||
numSteps: 3,
|
numSteps: 3,
|
||||||
body: [LinkWatchScreen(step:1)],
|
body: [LinkWatchScreen(step: 1)],
|
||||||
footer: [continueBtn],
|
footer: [continueBtn],
|
||||||
nextStep: ()=>{},
|
nextStep: () => {},
|
||||||
previousStep: ()=>{}
|
previousStep: () => {},
|
||||||
),
|
),
|
||||||
FormStepLayout(
|
FormStepLayout(
|
||||||
title: "Vincula su correa\ny su reloj",
|
title: "Vincula su correa\ny su reloj",
|
||||||
currentStep: 2,
|
currentStep: 2,
|
||||||
numSteps: 3,
|
numSteps: 3,
|
||||||
body: [LinkWatchScreen(step:2)],
|
body: [LinkWatchScreen(step: 2)],
|
||||||
footer: [continueBtn],
|
footer: [continueBtn],
|
||||||
nextStep: ()=>{},
|
nextStep: () => {},
|
||||||
previousStep: ()=>{}
|
previousStep: () => {},
|
||||||
|
),
|
||||||
|
AccountCreatedScreen(
|
||||||
|
navigationContract: navigationContract,
|
||||||
|
kidAccount: true,
|
||||||
),
|
),
|
||||||
AccountCreatedScreen(navigationContract: navigationContract, kidAccount: true)
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
abstract class LinkPhoneUseCase {
|
||||||
|
Future<void> requestCode({required String phone});
|
||||||
|
|
||||||
|
Future<void> verifyCode({required String phone, required String code});
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import 'package:auth/src/core/domain/repositories/auth_repository.dart';
|
||||||
|
import 'package:auth/src/features/link_phone/domain/use_cases/link_phone_use_case.dart';
|
||||||
|
|
||||||
|
class LinkPhoneUseCaseImpl implements LinkPhoneUseCase {
|
||||||
|
LinkPhoneUseCaseImpl(this._repository);
|
||||||
|
|
||||||
|
final AuthRepository _repository;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> requestCode({required String phone}) {
|
||||||
|
return _repository.requestPhoneCode(phone: phone);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> verifyCode({required String phone, required String code}) {
|
||||||
|
return _repository.verifyPhoneCode(phone: phone, code: code);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:auth/src/login/presentation/link_phone_screen.dart';
|
import 'package:auth/src/features/link_phone/presentation/link_phone_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
import 'package:auth/src/features/link_phone/presentation/link_phone_view_model.dart';
|
||||||
|
import 'package:design_system/src/dropdowns/country_prefix_picker.dart';
|
||||||
|
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';
|
||||||
|
|
||||||
|
class LinkPhoneScreen extends ConsumerWidget {
|
||||||
|
final NavigationContract navigationContract;
|
||||||
|
|
||||||
|
const LinkPhoneScreen({super.key, required this.navigationContract});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final theme = ref.watch(themePortProvider);
|
||||||
|
|
||||||
|
final viewModel = ref.read(linkPhoneViewModelProvider.notifier);
|
||||||
|
final viewState = ref.watch(linkPhoneViewModelProvider);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.translate(I18n.linkPhoneTitle),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 30,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
letterSpacing: 0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
Text(
|
||||||
|
context.translate(I18n.linkPhoneSubtitle),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(fontSize: 16, letterSpacing: 0),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 48),
|
||||||
|
|
||||||
|
Column(
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.bottomLeft,
|
||||||
|
child: Text(
|
||||||
|
context.translate(I18n.mobilePhone),
|
||||||
|
style: const TextStyle(fontSize: 14, letterSpacing: 0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
spacing: 10,
|
||||||
|
children: [
|
||||||
|
CountryPrefixPicker(
|
||||||
|
initialCountryCode: viewState.dialCode,
|
||||||
|
onChanged: (country) {
|
||||||
|
viewModel.updateDialCode(
|
||||||
|
country.dialCode ?? viewState.dialCode,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: CustomTextField(
|
||||||
|
controller: viewModel.phoneNumberController,
|
||||||
|
hint: context.translate(I18n.phoneNumber),
|
||||||
|
numeric: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
if (viewState.errorMessage.isNotEmpty) ...[
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
viewState.errorMessage,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Color.fromRGBO(239, 17, 17, 1),
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
|
PrimaryButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await viewModel.requestCode();
|
||||||
|
final updatedState = ref.read(linkPhoneViewModelProvider);
|
||||||
|
if (updatedState.errorMessage.isEmpty) {
|
||||||
|
navigationContract.pushTo(AppRoutes.phoneCode);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
text: context.translate(I18n.next),
|
||||||
|
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import 'package:auth/src/features/link_phone/presentation/providers/link_phone_provider.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
import 'package:auth/src/features/link_phone/domain/use_cases/link_phone_use_case.dart';
|
||||||
|
import 'package:auth/src/features/link_phone/presentation/link_phone_view_state.dart';
|
||||||
|
|
||||||
|
final linkPhoneViewModelProvider =
|
||||||
|
NotifierProvider.autoDispose<LinkPhoneViewModel, LinkPhoneViewState>(
|
||||||
|
LinkPhoneViewModel.new,
|
||||||
|
);
|
||||||
|
|
||||||
|
class LinkPhoneViewModel extends Notifier<LinkPhoneViewState> {
|
||||||
|
late final LinkPhoneUseCase _linkPhoneUseCase;
|
||||||
|
late final TextEditingController phoneNumberController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
LinkPhoneViewState build() {
|
||||||
|
_linkPhoneUseCase = ref.read(linkPhoneUseCaseProvider);
|
||||||
|
|
||||||
|
phoneNumberController = TextEditingController();
|
||||||
|
phoneNumberController.addListener(_onPhoneNumberChanged);
|
||||||
|
|
||||||
|
ref.onDispose(disposeControllers);
|
||||||
|
|
||||||
|
return const LinkPhoneViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onPhoneNumberChanged() {
|
||||||
|
final raw = phoneNumberController.text;
|
||||||
|
state = state.copyWith(phoneNumber: raw, errorMessage: '');
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateDialCode(String dialCode) {
|
||||||
|
state = state.copyWith(dialCode: dialCode, errorMessage: '');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> requestCode() async {
|
||||||
|
final trimmedNumber = state.phoneNumber.trim();
|
||||||
|
|
||||||
|
if (trimmedNumber.isEmpty) {
|
||||||
|
state = state.copyWith(errorMessage: 'El teléfono no puede estar vacío');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final fullPhone = '${state.dialCode}$trimmedNumber';
|
||||||
|
|
||||||
|
state = state.copyWith(
|
||||||
|
isLoading: true,
|
||||||
|
errorMessage: '',
|
||||||
|
codeRequested: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await _linkPhoneUseCase.requestCode(phone: fullPhone);
|
||||||
|
if (!ref.mounted) return;
|
||||||
|
|
||||||
|
state = state.copyWith(
|
||||||
|
isLoading: false,
|
||||||
|
errorMessage: '',
|
||||||
|
codeRequested: true,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
if (!ref.mounted) return;
|
||||||
|
|
||||||
|
state = state.copyWith(
|
||||||
|
isLoading: false,
|
||||||
|
errorMessage: e.toString(),
|
||||||
|
codeRequested: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void disposeControllers() {
|
||||||
|
phoneNumberController.removeListener(_onPhoneNumberChanged);
|
||||||
|
phoneNumberController.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'link_phone_view_state.freezed.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class LinkPhoneViewState with _$LinkPhoneViewState {
|
||||||
|
const factory LinkPhoneViewState({
|
||||||
|
@Default('') String phoneNumber,
|
||||||
|
@Default('+34') String dialCode,
|
||||||
|
@Default('') String errorMessage,
|
||||||
|
@Default(false) bool isLoading,
|
||||||
|
@Default(false) bool codeRequested,
|
||||||
|
}) = _LinkPhoneViewState;
|
||||||
|
}
|
||||||
@@ -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 'link_phone_view_state.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LinkPhoneViewState {
|
||||||
|
|
||||||
|
String get phoneNumber; String get dialCode; String get errorMessage; bool get isLoading; bool get codeRequested;
|
||||||
|
/// Create a copy of LinkPhoneViewState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$LinkPhoneViewStateCopyWith<LinkPhoneViewState> get copyWith => _$LinkPhoneViewStateCopyWithImpl<LinkPhoneViewState>(this as LinkPhoneViewState, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $LinkPhoneViewStateCopyWith<$Res> {
|
||||||
|
factory $LinkPhoneViewStateCopyWith(LinkPhoneViewState value, $Res Function(LinkPhoneViewState) _then) = _$LinkPhoneViewStateCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$LinkPhoneViewStateCopyWithImpl<$Res>
|
||||||
|
implements $LinkPhoneViewStateCopyWith<$Res> {
|
||||||
|
_$LinkPhoneViewStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final LinkPhoneViewState _self;
|
||||||
|
final $Res Function(LinkPhoneViewState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LinkPhoneViewState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // 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 String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,codeRequested: null == codeRequested ? _self.codeRequested : codeRequested // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [LinkPhoneViewState].
|
||||||
|
extension LinkPhoneViewStatePatterns on LinkPhoneViewState {
|
||||||
|
/// 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 extends Object?>(TResult Function( _LinkPhoneViewState value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LinkPhoneViewState() 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 extends Object?>(TResult Function( _LinkPhoneViewState value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LinkPhoneViewState():
|
||||||
|
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 extends Object?>(TResult? Function( _LinkPhoneViewState value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LinkPhoneViewState() 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 extends Object?>(TResult Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LinkPhoneViewState() when $default != null:
|
||||||
|
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);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 extends Object?>(TResult Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LinkPhoneViewState():
|
||||||
|
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);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 extends Object?>(TResult? Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LinkPhoneViewState() when $default != null:
|
||||||
|
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _LinkPhoneViewState implements LinkPhoneViewState {
|
||||||
|
const _LinkPhoneViewState({this.phoneNumber = '', this.dialCode = '+34', this.errorMessage = '', this.isLoading = false, this.codeRequested = false});
|
||||||
|
|
||||||
|
|
||||||
|
@override@JsonKey() final String phoneNumber;
|
||||||
|
@override@JsonKey() final String dialCode;
|
||||||
|
@override@JsonKey() final String errorMessage;
|
||||||
|
@override@JsonKey() final bool isLoading;
|
||||||
|
@override@JsonKey() final bool codeRequested;
|
||||||
|
|
||||||
|
/// Create a copy of LinkPhoneViewState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$LinkPhoneViewStateCopyWith<_LinkPhoneViewState> get copyWith => __$LinkPhoneViewStateCopyWithImpl<_LinkPhoneViewState>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$LinkPhoneViewStateCopyWith<$Res> implements $LinkPhoneViewStateCopyWith<$Res> {
|
||||||
|
factory _$LinkPhoneViewStateCopyWith(_LinkPhoneViewState value, $Res Function(_LinkPhoneViewState) _then) = __$LinkPhoneViewStateCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$LinkPhoneViewStateCopyWithImpl<$Res>
|
||||||
|
implements _$LinkPhoneViewStateCopyWith<$Res> {
|
||||||
|
__$LinkPhoneViewStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _LinkPhoneViewState _self;
|
||||||
|
final $Res Function(_LinkPhoneViewState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LinkPhoneViewState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,}) {
|
||||||
|
return _then(_LinkPhoneViewState(
|
||||||
|
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // 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 String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,codeRequested: null == codeRequested ? _self.codeRequested : codeRequested // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import 'package:auth/src/core/providers/auth_repository_provider.dart';
|
||||||
|
import 'package:auth/src/features/link_phone/domain/use_cases/link_phone_use_case.dart';
|
||||||
|
import 'package:auth/src/features/link_phone/domain/use_cases/link_phone_use_case_impl.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
final linkPhoneUseCaseProvider = Provider.autoDispose<LinkPhoneUseCase>((ref) {
|
||||||
|
final authRepository = ref.read(authRepositoryProvider);
|
||||||
|
return LinkPhoneUseCaseImpl(authRepository);
|
||||||
|
});
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:auth/src/login/presentation/login_screen.dart';
|
import 'package:auth/src/features/login/presentation/login_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:auth/src/login/presentation/phone_code_screen.dart';
|
import 'package:auth/src/features/login/presentation/phone_code_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:auth/src/login/presentation/loading_google_screen.dart';
|
import 'package:auth/src/features/login/presentation/loading_google_screen.dart';
|
||||||
import 'package:auth/src/sign_up/signup_screen.dart';
|
import 'package:auth/src/features/sign_up/signup_screen.dart';
|
||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@@ -15,7 +15,7 @@ class LoginScreen extends ConsumerStatefulWidget {
|
|||||||
ConsumerState<ConsumerStatefulWidget> createState() => _LoginScreenState();
|
ConsumerState<ConsumerStatefulWidget> createState() => _LoginScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LoginScreenState extends ConsumerState<LoginScreen>{
|
class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||||
bool passwordVisible = false;
|
bool passwordVisible = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -28,7 +28,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen>{
|
|||||||
Column(
|
Column(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.check, color: theme.getColorFor(ThemeCode.buttonPrimary), size: 50),
|
Icon(
|
||||||
|
Icons.check,
|
||||||
|
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||||
|
size: 50,
|
||||||
|
),
|
||||||
Text(
|
Text(
|
||||||
// context.translate(I18n.example)
|
// context.translate(I18n.example)
|
||||||
"¡Te damos la bienvenida!",
|
"¡Te damos la bienvenida!",
|
||||||
@@ -51,43 +55,48 @@ class _LoginScreenState extends ConsumerState<LoginScreen>{
|
|||||||
spacing: 12,
|
spacing: 12,
|
||||||
children: [
|
children: [
|
||||||
CustomTextField(
|
CustomTextField(
|
||||||
showPassword: passwordVisible,
|
showPassword: passwordVisible,
|
||||||
label: "Contraseña",
|
label: "Contraseña",
|
||||||
hint: "********"
|
hint: "********",
|
||||||
),
|
),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
child: CustomTextButton(
|
child: CustomTextButton(
|
||||||
text: "¿Has olvidado la contraseña?",
|
text: "¿Has olvidado la contraseña?",
|
||||||
onPressed: () =>
|
onPressed: () => widget.navigationContract.pushTo(
|
||||||
widget.navigationContract.pushTo(AppRoutes.recoverPassword),
|
AppRoutes.recoverPassword,
|
||||||
|
),
|
||||||
size: 16,
|
size: 16,
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
PrimaryButton(
|
PrimaryButton(
|
||||||
onPressed: () => widget.navigationContract.goTo(AppRoutes.dashboardHome),
|
onPressed: () =>
|
||||||
text: "Iniciar sesión",
|
widget.navigationContract.goTo(AppRoutes.dashboardHome),
|
||||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
text: "Iniciar sesión",
|
||||||
|
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.only(top: 24),
|
padding: EdgeInsets.only(top: 24),
|
||||||
child: Column(
|
child: Column(
|
||||||
spacing: 24,
|
spacing: 24,
|
||||||
children: [
|
children: [
|
||||||
Stack(children: [
|
Stack(
|
||||||
Divider(endIndent: 74, indent: 74),
|
children: [
|
||||||
Align(
|
Divider(endIndent: 74, indent: 74),
|
||||||
|
Align(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||||
child: Text("o continúa con"),
|
child: Text("o continúa con"),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
spacing: 20,
|
spacing: 20,
|
||||||
children: [
|
children: [
|
||||||
@@ -105,7 +114,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>{
|
|||||||
label: "Google",
|
label: "Google",
|
||||||
),
|
),
|
||||||
SecondaryButton(
|
SecondaryButton(
|
||||||
onPressed: ()=>{},
|
onPressed: () => {},
|
||||||
radius: 16,
|
radius: 16,
|
||||||
padding: 44,
|
padding: 44,
|
||||||
icon: Icons.apple,
|
icon: Icons.apple,
|
||||||
@@ -121,18 +130,23 @@ class _LoginScreenState extends ConsumerState<LoginScreen>{
|
|||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"¿No tienes cuenta?",
|
"¿No tienes cuenta?",
|
||||||
style: TextStyle(fontSize: 18, letterSpacing: 0)
|
style: TextStyle(fontSize: 18, letterSpacing: 0),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => widget.navigationContract.goTo(AppRoutes.signup),
|
onPressed: () =>
|
||||||
|
widget.navigationContract.goTo(AppRoutes.signup),
|
||||||
child: Text(
|
child: Text(
|
||||||
"Crear una ahora",
|
"Crear una ahora",
|
||||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500, letterSpacing: 0)
|
style: TextStyle(
|
||||||
)
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
letterSpacing: 0,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@@ -153,8 +167,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen>{
|
|||||||
itemCount: content.length,
|
itemCount: content.length,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,12 +5,10 @@ import 'package:navigation/navigation.dart';
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
class PhoneCodeScreen extends ConsumerWidget {
|
class PhoneCodeScreen extends ConsumerWidget {
|
||||||
// final String phone;
|
|
||||||
final NavigationContract navigationContract;
|
final NavigationContract navigationContract;
|
||||||
|
|
||||||
PhoneCodeScreen({super.key, required this.navigationContract});
|
PhoneCodeScreen({super.key, required this.navigationContract});
|
||||||
|
|
||||||
// class PhoneCodeScreenState extends State<PhoneCodeScreen> {
|
|
||||||
final focusNodes = List<FocusNode>.generate(6, (int i) {
|
final focusNodes = List<FocusNode>.generate(6, (int i) {
|
||||||
return FocusNode();
|
return FocusNode();
|
||||||
});
|
});
|
||||||
@@ -34,7 +32,10 @@ class PhoneCodeScreen extends ConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Conéctate",
|
"Conéctate",
|
||||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 30,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Text.rich(
|
Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
@@ -55,7 +56,9 @@ class PhoneCodeScreen extends ConsumerWidget {
|
|||||||
child: TextField(
|
child: TextField(
|
||||||
focusNode: focusNodes[i],
|
focusNode: focusNodes[i],
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.digitsOnly,
|
||||||
|
],
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "0",
|
hintText: "0",
|
||||||
@@ -78,7 +81,9 @@ class PhoneCodeScreen extends ConsumerWidget {
|
|||||||
spacing: 24,
|
spacing: 24,
|
||||||
children: [
|
children: [
|
||||||
PrimaryButton(
|
PrimaryButton(
|
||||||
onPressed: () => {navigationContract.pushTo(AppRoutes.login)},
|
onPressed: () => {
|
||||||
|
navigationContract.pushTo(AppRoutes.login),
|
||||||
|
},
|
||||||
text: "Entrar",
|
text: "Entrar",
|
||||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||||
),
|
),
|
||||||
@@ -87,7 +92,11 @@ class PhoneCodeScreen extends ConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"¿No lo has recibido?",
|
"¿No lo has recibido?",
|
||||||
style: TextStyle(fontSize: 18, letterSpacing: 0, height: 1.5),
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
letterSpacing: 0,
|
||||||
|
height: 1.5,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
CustomTextButton(
|
CustomTextButton(
|
||||||
onPressed: () => {},
|
onPressed: () => {},
|
||||||
@@ -96,7 +105,7 @@ class PhoneCodeScreen extends ConsumerWidget {
|
|||||||
weight: FontWeight.w500,
|
weight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Spacer(flex: 10),
|
Spacer(flex: 10),
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:auth/src/onboarding/presentation/onboarding_screen.dart';
|
import 'package:auth/src/features/onboarding/presentation/onboarding_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
import 'package:auth/src/features/onboarding/domain/onboarding_page.dart';
|
||||||
|
import 'package:auth/src/features/onboarding/presentation/onboarding_view_model.dart';
|
||||||
|
import 'package:auth/src/features/onboarding/presentation/widgets/onboarding_content.dart';
|
||||||
|
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';
|
||||||
|
|
||||||
|
final onboardingPageControllerProvider = Provider.autoDispose<PageController>((
|
||||||
|
ref,
|
||||||
|
) {
|
||||||
|
final controller = PageController();
|
||||||
|
ref.onDispose(controller.dispose);
|
||||||
|
return controller;
|
||||||
|
});
|
||||||
|
|
||||||
|
class OnboardingScreen extends ConsumerWidget {
|
||||||
|
final NavigationContract navigationContract;
|
||||||
|
|
||||||
|
const OnboardingScreen({super.key, required this.navigationContract});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final state = ref.watch(onBoardingViewModelProvider);
|
||||||
|
final viewModel = ref.read(onBoardingViewModelProvider.notifier);
|
||||||
|
final pageController = ref.watch(onboardingPageControllerProvider);
|
||||||
|
|
||||||
|
final isLast = state.cardIndex >= onboardingPages.length - 1;
|
||||||
|
|
||||||
|
void goToNext() {
|
||||||
|
if (isLast) {
|
||||||
|
navigationContract.goTo(AppRoutes.linkPhone);
|
||||||
|
} else {
|
||||||
|
pageController.nextPage(
|
||||||
|
duration: const Duration(milliseconds: 400),
|
||||||
|
curve: Curves.easeOut,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Color(0xFFF7F7F7),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: PageView.builder(
|
||||||
|
controller: pageController,
|
||||||
|
itemCount: onboardingPages.length,
|
||||||
|
onPageChanged: viewModel.onPageChanged,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final page = onboardingPages[index];
|
||||||
|
return OnboardingContent(
|
||||||
|
image: page.image,
|
||||||
|
title: page.title,
|
||||||
|
subtitle: page.subtitle,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
StepIndicator(
|
||||||
|
current: state.cardIndex + 1,
|
||||||
|
total: onboardingPages.length,
|
||||||
|
color: const Color(0xFF4B4B4B),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 48),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
width: double.infinity,
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: goToNext,
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
backgroundColor: isLast
|
||||||
|
? const Color(0xFF329E95)
|
||||||
|
: const Color(0xFF4B4B4B),
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 16,
|
||||||
|
horizontal: 24,
|
||||||
|
),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(18),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
isLast
|
||||||
|
? context.translate(I18n.start)
|
||||||
|
: context.translate(I18n.next),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
SizedBox(
|
||||||
|
height: 48,
|
||||||
|
child: Center(
|
||||||
|
child: isLast
|
||||||
|
? const SizedBox.shrink()
|
||||||
|
: TextButton(
|
||||||
|
onPressed: () =>
|
||||||
|
navigationContract.goTo(AppRoutes.linkPhone),
|
||||||
|
child: Text(
|
||||||
|
context.translate(I18n.skip),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xFF4B4B4B),
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 36),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
import 'package:auth/src/onboarding/presentation/onboarding_view_state.dart';
|
import 'package:auth/src/features/onboarding/presentation/onboarding_view_state.dart';
|
||||||
|
|
||||||
final onBoardingViewModelProvider =
|
final onBoardingViewModelProvider =
|
||||||
NotifierProvider.autoDispose<OnBoardingViewModel, OnboardingViewState>(
|
NotifierProvider.autoDispose<OnBoardingViewModel, OnboardingViewState>(
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:sf_localizations/sf_localizations.dart';
|
||||||
|
|
||||||
|
class OnboardingContent extends StatelessWidget {
|
||||||
|
final String image;
|
||||||
|
final String title;
|
||||||
|
final String subtitle;
|
||||||
|
|
||||||
|
const OnboardingContent({
|
||||||
|
super.key,
|
||||||
|
required this.image,
|
||||||
|
required this.title,
|
||||||
|
required this.subtitle,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Flexible(flex: 3, child: SvgPicture.asset(image)),
|
||||||
|
const SizedBox(height: 48),
|
||||||
|
Text(
|
||||||
|
context.translate(title),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 30,
|
||||||
|
height: 1.25,
|
||||||
|
letterSpacing: 0,
|
||||||
|
color: Color(0xFF4B4B4B),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
context.translate(subtitle),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
height: 1.5,
|
||||||
|
letterSpacing: 0,
|
||||||
|
color: Color(0xFF4B4B4B),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:auth/src/recover_password/presentation/sent_screen.dart';
|
import 'package:auth/src/features/recover_password/presentation/sent_screen.dart';
|
||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:navigation/navigation.dart';
|
import 'package:navigation/navigation.dart';
|
||||||
@@ -47,26 +47,30 @@ class RestorePasswordScreen extends ConsumerWidget {
|
|||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.bottomLeft,
|
alignment: Alignment.bottomLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
"Teléfono móvil",
|
"Teléfono móvil",
|
||||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||||
)
|
),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
children: [
|
children: [
|
||||||
CustomDropdown(
|
CustomDropdown(
|
||||||
value: 0,
|
value: 0,
|
||||||
items: [Icon(Icons.outlined_flag), Icon(Icons.outlined_flag), Icon(Icons.outlined_flag)],
|
items: [
|
||||||
onChanged: (value)=> {},
|
Icon(Icons.outlined_flag),
|
||||||
|
Icon(Icons.outlined_flag),
|
||||||
|
Icon(Icons.outlined_flag),
|
||||||
|
],
|
||||||
|
onChanged: (value) => {},
|
||||||
width: 80,
|
width: 80,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CustomTextField(
|
child: CustomTextField(
|
||||||
hint: "Teléfono",
|
hint: "Teléfono",
|
||||||
numeric: true
|
numeric: true,
|
||||||
)
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -75,11 +79,14 @@ class RestorePasswordScreen extends ConsumerWidget {
|
|||||||
Row(
|
Row(
|
||||||
spacing: 20,
|
spacing: 20,
|
||||||
children: [
|
children: [
|
||||||
Expanded( child: SecondaryButton(
|
Expanded(
|
||||||
|
child: SecondaryButton(
|
||||||
onPressed: () => {Navigator.pop(context)},
|
onPressed: () => {Navigator.pop(context)},
|
||||||
text: "Volver"
|
text: "Volver",
|
||||||
)),
|
),
|
||||||
Expanded( child: PrimaryButton(
|
),
|
||||||
|
Expanded(
|
||||||
|
child: PrimaryButton(
|
||||||
onPressed: () => {
|
onPressed: () => {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
@@ -90,8 +97,9 @@ class RestorePasswordScreen extends ConsumerWidget {
|
|||||||
},
|
},
|
||||||
text: "Enviar",
|
text: "Enviar",
|
||||||
size: 16,
|
size: 16,
|
||||||
color: theme.getColorFor(ThemeCode.buttonSecondary)
|
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:auth/src/recover_password/presentation/new_password_screen.dart';
|
import 'package:auth/src/features/recover_password/presentation/new_password_screen.dart';
|
||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@@ -6,10 +6,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||||||
class SentScreen extends ConsumerWidget {
|
class SentScreen extends ConsumerWidget {
|
||||||
final String format;
|
final String format;
|
||||||
|
|
||||||
const SentScreen({
|
const SentScreen({super.key, required this.format});
|
||||||
super.key,
|
|
||||||
required this.format
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -27,7 +24,11 @@ class SentScreen extends ConsumerWidget {
|
|||||||
Text(
|
Text(
|
||||||
"Recuperar contraseña",
|
"Recuperar contraseña",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 30, letterSpacing: 0),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 30,
|
||||||
|
letterSpacing: 0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
@@ -38,9 +39,9 @@ class SentScreen extends ConsumerWidget {
|
|||||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
format=="email"
|
format == "email"
|
||||||
?"Correo enviado correctamente"
|
? "Correo enviado correctamente"
|
||||||
:"SMS enviado correctamente",
|
: "SMS enviado correctamente",
|
||||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
@@ -50,16 +51,16 @@ class SentScreen extends ConsumerWidget {
|
|||||||
spacing: 16,
|
spacing: 16,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
format=="email"
|
format == "email"
|
||||||
?"Revisa tu email y haz clic en el enlace para crear una nueva contraseña."
|
? "Revisa tu email y haz clic en el enlace para crear una nueva contraseña."
|
||||||
:"Revisa tu móvil y sigue las instrucciones para crear una nueva contraseña.",
|
: "Revisa tu móvil y sigue las instrucciones para crear una nueva contraseña.",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(fontSize: 18, letterSpacing: 0),
|
style: TextStyle(fontSize: 18, letterSpacing: 0),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
format=="email"
|
format == "email"
|
||||||
?"Si no recibes el correo en unos minutos, revisa tu carpeta de spam o pulsa \"Reenviar correo\"."
|
? "Si no recibes el correo en unos minutos, revisa tu carpeta de spam o pulsa \"Reenviar correo\"."
|
||||||
:"Si no recibes el SMS en unos minutos, asegúrate de tener cobertura o pulsa \"Reenviar SMS \".",
|
: "Si no recibes el SMS en unos minutos, asegúrate de tener cobertura o pulsa \"Reenviar SMS \".",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||||
),
|
),
|
||||||
@@ -68,22 +69,22 @@ class SentScreen extends ConsumerWidget {
|
|||||||
Row(
|
Row(
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
children: [
|
children: [
|
||||||
Expanded( child: SecondaryButton(
|
Expanded(
|
||||||
onPressed: () => {},
|
child: SecondaryButton(
|
||||||
text: format=="email"
|
onPressed: () => {},
|
||||||
?"Reenviar correo"
|
text: format == "email"
|
||||||
:"Reenviar SMS"
|
? "Reenviar correo"
|
||||||
)),
|
: "Reenviar SMS",
|
||||||
|
),
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: PrimaryButton(
|
child: PrimaryButton(
|
||||||
onPressed: ()=>Navigator.push(
|
onPressed: () => Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(builder: (_) => NewPasswordScreen()),
|
||||||
builder: (_) => NewPasswordScreen(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
text: "Continuar",
|
text: "Continuar",
|
||||||
color: theme.getColorFor(ThemeCode.buttonSecondary)
|
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:auth/src/recover_password/presentation/restore_password_screen.dart';
|
import 'package:auth/src/features/recover_password/presentation/restore_password_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:auth/src/sign_up/signup_screen.dart';
|
import 'package:auth/src/features/sign_up/signup_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import 'package:auth/src/widgets/layouts/form_step_layout.dart';
|
import 'package:auth/src/widgets/layouts/form_step_layout.dart';
|
||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:auth/src/sign_up/signup_address_screen.dart';
|
import 'package:auth/src/features/sign_up/signup_address_screen.dart';
|
||||||
import 'package:auth/src/sign_up/signup_personal_screen.dart';
|
import 'package:auth/src/features/sign_up/signup_personal_screen.dart';
|
||||||
import 'package:auth/src/sign_up/signup_user_screen.dart';
|
import 'package:auth/src/features/sign_up/signup_user_screen.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:navigation/navigation.dart';
|
import 'package:navigation/navigation.dart';
|
||||||
@@ -13,10 +13,7 @@ import 'account_created_screen.dart';
|
|||||||
class SignupScreen extends ConsumerStatefulWidget {
|
class SignupScreen extends ConsumerStatefulWidget {
|
||||||
NavigationContract navigationContract;
|
NavigationContract navigationContract;
|
||||||
|
|
||||||
SignupScreen({
|
SignupScreen({super.key, required this.navigationContract});
|
||||||
super.key,
|
|
||||||
required this.navigationContract
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<SignupScreen> createState() => _SignupScreenState();
|
ConsumerState<SignupScreen> createState() => _SignupScreenState();
|
||||||
@@ -37,8 +34,9 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
|
|||||||
return [
|
return [
|
||||||
FormStepLayout(
|
FormStepLayout(
|
||||||
title: "Crea tu usuario",
|
title: "Crea tu usuario",
|
||||||
subtitle: "Con tu email y tu número podremos mantenerte siempre informado",
|
subtitle:
|
||||||
supertitle: "Usuario y contacto",
|
"Con tu email y tu número podremos mantenerte siempre informado",
|
||||||
|
supertitle: "Usuario y contacto",
|
||||||
currentStep: 1,
|
currentStep: 1,
|
||||||
numSteps: 3,
|
numSteps: 3,
|
||||||
body: [SignupPersonalScreen()],
|
body: [SignupPersonalScreen()],
|
||||||
@@ -46,20 +44,26 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
|
|||||||
Row(
|
Row(
|
||||||
spacing: 16,
|
spacing: 16,
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: SecondaryButton(
|
Expanded(
|
||||||
onPressed: ()=>{},
|
child: SecondaryButton(
|
||||||
text: "Atrás",
|
onPressed: () => {},
|
||||||
size: 16,
|
text: "Atrás",
|
||||||
)),
|
size: 16,
|
||||||
Expanded(child: PrimaryButton(
|
),
|
||||||
onPressed: ()=>{setState(() {
|
),
|
||||||
currentStep++;
|
Expanded(
|
||||||
})},
|
child: PrimaryButton(
|
||||||
text: "Siguiente",
|
onPressed: () => {
|
||||||
size: 16,
|
setState(() {
|
||||||
color: theme.getColorFor(ThemeCode.buttonSecondary)
|
currentStep++;
|
||||||
))
|
}),
|
||||||
]
|
},
|
||||||
|
text: "Siguiente",
|
||||||
|
size: 16,
|
||||||
|
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
CheckboxListTile(
|
CheckboxListTile(
|
||||||
value: acceptTerms,
|
value: acceptTerms,
|
||||||
@@ -74,42 +78,57 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
|
|||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||||
controlAffinity: ListTileControlAffinity.leading,
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
nextStep: ()=>{setState(() {
|
nextStep: () => {
|
||||||
currentStep++;
|
setState(() {
|
||||||
})},
|
currentStep++;
|
||||||
previousStep: ()=>{},
|
}),
|
||||||
|
},
|
||||||
|
previousStep: () => {},
|
||||||
),
|
),
|
||||||
FormStepLayout(
|
FormStepLayout(
|
||||||
title: "Tu dirección",
|
title: "Tu dirección",
|
||||||
subtitle: "Tu dirección nos ayudará a verificar y mantener la seguridad de tu cuenta",
|
subtitle:
|
||||||
|
"Tu dirección nos ayudará a verificar y mantener la seguridad de tu cuenta",
|
||||||
supertitle: "Domicilio",
|
supertitle: "Domicilio",
|
||||||
currentStep: 2,
|
currentStep: 2,
|
||||||
numSteps: 3,
|
numSteps: 3,
|
||||||
body: [SignupAddressScreen()],
|
body: [SignupAddressScreen()],
|
||||||
nextStep: ()=>{setState(() {
|
nextStep: () => {
|
||||||
currentStep++;
|
setState(() {
|
||||||
})},
|
currentStep++;
|
||||||
previousStep: ()=>{setState(() {
|
}),
|
||||||
currentStep--;
|
},
|
||||||
})},
|
previousStep: () => {
|
||||||
|
setState(() {
|
||||||
|
currentStep--;
|
||||||
|
}),
|
||||||
|
},
|
||||||
),
|
),
|
||||||
FormStepLayout(
|
FormStepLayout(
|
||||||
title: "Identifícate",
|
title: "Identifícate",
|
||||||
subtitle: "Contraseña mínima de 8 caracteres, con una mayúscula, un número y un carácter especial",
|
subtitle:
|
||||||
|
"Contraseña mínima de 8 caracteres, con una mayúscula, un número y un carácter especial",
|
||||||
supertitle: "Usuario y contacto",
|
supertitle: "Usuario y contacto",
|
||||||
currentStep: 3,
|
currentStep: 3,
|
||||||
numSteps: 3,
|
numSteps: 3,
|
||||||
body: [SignupUserScreen()],
|
body: [SignupUserScreen()],
|
||||||
nextStep: ()=>{setState(() {
|
nextStep: () => {
|
||||||
currentStep++;
|
setState(() {
|
||||||
})},
|
currentStep++;
|
||||||
previousStep: ()=>{setState(() {
|
}),
|
||||||
currentStep--;
|
},
|
||||||
})},
|
previousStep: () => {
|
||||||
|
setState(() {
|
||||||
|
currentStep--;
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
AccountCreatedScreen(
|
||||||
|
navigationContract: widget.navigationContract,
|
||||||
|
kidAccount: false,
|
||||||
),
|
),
|
||||||
AccountCreatedScreen(navigationContract: widget.navigationContract, kidAccount: false)
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import 'package:design_system/design_system.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:navigation/navigation.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
|
|
||||||
class LinkPhoneScreen extends ConsumerWidget {
|
|
||||||
final NavigationContract navigationContract;
|
|
||||||
|
|
||||||
const LinkPhoneScreen({super.key, required this.navigationContract});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final theme = ref.watch(themePortProvider);
|
|
||||||
|
|
||||||
// TextEditingController phoneController = TextEditingController();
|
|
||||||
// String? phone;
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
|
||||||
body: SafeArea(
|
|
||||||
child: Container(
|
|
||||||
margin: EdgeInsets.symmetric(horizontal: 24),
|
|
||||||
child: Expanded(
|
|
||||||
child: Center(
|
|
||||||
child: Column(
|
|
||||||
spacing: 48,
|
|
||||||
children: [
|
|
||||||
Spacer(flex: 8),
|
|
||||||
Text(
|
|
||||||
"¡Nos alegra mucho tenerte por aquí!",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500, letterSpacing: 0),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"Para poder entrar de forma segura, te vamos a enviar un código al teléfono",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(fontSize: 16, letterSpacing: 0),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
spacing: 8,
|
|
||||||
children: [
|
|
||||||
Align(alignment: Alignment.bottomLeft, child: Text(
|
|
||||||
"Teléfono móvil",
|
|
||||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
|
||||||
)),
|
|
||||||
Row(
|
|
||||||
spacing: 10,
|
|
||||||
children: [
|
|
||||||
CustomDropdown(
|
|
||||||
value: 0,
|
|
||||||
items: [Icon(Icons.outlined_flag), Icon(Icons.outlined_flag), Icon(Icons.outlined_flag)],
|
|
||||||
onChanged: (value)=> {},
|
|
||||||
width: 80,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: CustomTextField(
|
|
||||||
hint: "Teléfono",
|
|
||||||
numeric: true
|
|
||||||
)
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
PrimaryButton(
|
|
||||||
onPressed: () => navigationContract.pushTo(AppRoutes.phoneCode),
|
|
||||||
text: "Siguiente",
|
|
||||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
|
||||||
),
|
|
||||||
Spacer(flex: 10)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
import 'package:auth/src/onboarding/domain/onboarding_page.dart';
|
|
||||||
import 'package:auth/src/onboarding/presentation/onboarding_view_model.dart';
|
|
||||||
import 'package:auth/src/onboarding/presentation/widgets/onboarding_content.dart';
|
|
||||||
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';
|
|
||||||
|
|
||||||
final onboardingPageControllerProvider = Provider.autoDispose<PageController>((
|
|
||||||
ref,
|
|
||||||
) {
|
|
||||||
final controller = PageController();
|
|
||||||
ref.onDispose(controller.dispose);
|
|
||||||
return controller;
|
|
||||||
});
|
|
||||||
|
|
||||||
class OnboardingScreen extends ConsumerWidget {
|
|
||||||
final NavigationContract navigationContract;
|
|
||||||
|
|
||||||
const OnboardingScreen({super.key, required this.navigationContract});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final state = ref.watch(onBoardingViewModelProvider);
|
|
||||||
final viewModel = ref.read(onBoardingViewModelProvider.notifier);
|
|
||||||
final pageController = ref.watch(onboardingPageControllerProvider);
|
|
||||||
|
|
||||||
final isLast = state.cardIndex >= onboardingPages.length - 1;
|
|
||||||
|
|
||||||
void goToNext() {
|
|
||||||
if (isLast) {
|
|
||||||
navigationContract.goTo(AppRoutes.linkPhone);
|
|
||||||
} else {
|
|
||||||
pageController.nextPage(
|
|
||||||
duration: const Duration(milliseconds: 400),
|
|
||||||
curve: Curves.easeOut,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
body: SafeArea(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: PageView.builder(
|
|
||||||
controller: pageController,
|
|
||||||
itemCount: onboardingPages.length,
|
|
||||||
onPageChanged: viewModel.onPageChanged,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final page = onboardingPages[index];
|
|
||||||
return OnboardingContent(
|
|
||||||
image: page.image,
|
|
||||||
title: page.title,
|
|
||||||
subtitle: page.subtitle,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
StepIndicator(
|
|
||||||
current: state.cardIndex,
|
|
||||||
total: onboardingPages.length,
|
|
||||||
color: const Color(0xFF4A4A4A),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 38),
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
|
||||||
width: double.infinity,
|
|
||||||
child: TextButton(
|
|
||||||
onPressed: goToNext,
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
backgroundColor: isLast
|
|
||||||
? const Color(0xFF329E95)
|
|
||||||
: const Color(0xFF333333),
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 16,
|
|
||||||
horizontal: 24,
|
|
||||||
),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(18),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
isLast
|
|
||||||
? context.translate(I18n.start)
|
|
||||||
: context.translate(I18n.next),
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
SizedBox(
|
|
||||||
height: 48,
|
|
||||||
child: Center(
|
|
||||||
child: isLast
|
|
||||||
? const SizedBox.shrink()
|
|
||||||
: TextButton(
|
|
||||||
onPressed: () =>
|
|
||||||
navigationContract.goTo(AppRoutes.linkPhone),
|
|
||||||
child: Text(
|
|
||||||
context.translate(I18n.skip),
|
|
||||||
style: TextStyle(
|
|
||||||
color: Color(0xFF333333),
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 36),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
|
||||||
import 'package:sf_localizations/sf_localizations.dart';
|
|
||||||
|
|
||||||
class OnboardingContent extends StatelessWidget {
|
|
||||||
final String image;
|
|
||||||
final String title;
|
|
||||||
final String subtitle;
|
|
||||||
|
|
||||||
const OnboardingContent({
|
|
||||||
super.key,
|
|
||||||
required this.image,
|
|
||||||
required this.title,
|
|
||||||
required this.subtitle,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Flexible(flex: 3, child: SvgPicture.asset(image)),
|
|
||||||
const SizedBox(height: 48),
|
|
||||||
Text(
|
|
||||||
context.translate(title),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
fontSize: 28,
|
|
||||||
height: 1.4,
|
|
||||||
letterSpacing: 0.3,
|
|
||||||
color: Color(0xFF4A4A4A),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text(
|
|
||||||
context.translate(subtitle),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
height: 1.4,
|
|
||||||
letterSpacing: 0.3,
|
|
||||||
color: Color(0xFF9B9B9B),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,6 +22,8 @@ dependencies:
|
|||||||
path: ../../packages/navigation
|
path: ../../packages/navigation
|
||||||
sf_localizations:
|
sf_localizations:
|
||||||
path: ../../packages/sf_localizations
|
path: ../../packages/sf_localizations
|
||||||
|
sf_infrastructure:
|
||||||
|
path: ../../packages/sf_infrastructure
|
||||||
#dependencies go here
|
#dependencies go here
|
||||||
flutter_svg: ^2.2.1
|
flutter_svg: ^2.2.1
|
||||||
get_it: ^9.0.5
|
get_it: ^9.0.5
|
||||||
@@ -29,6 +31,8 @@ dependencies:
|
|||||||
flutter_riverpod: ^3.0.3
|
flutter_riverpod: ^3.0.3
|
||||||
freezed_annotation: ^3.1.0
|
freezed_annotation: ^3.1.0
|
||||||
freezed: ^3.2.3
|
freezed: ^3.2.3
|
||||||
|
dio: ^5.9.0
|
||||||
|
country_code_picker: ^3.4.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# melos_managed_dependency_overrides: dashboard_shell,design_system,home,notifications,profile,sf_shared,navigation,utils,sf_localizations,fonts
|
# melos_managed_dependency_overrides: dashboard_shell,design_system,home,notifications,profile,sf_shared,navigation,utils,sf_localizations,fonts,sf_infrastructure
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
dashboard_shell:
|
dashboard_shell:
|
||||||
path: ../dashboard_shell
|
path: ../dashboard_shell
|
||||||
@@ -14,6 +14,8 @@ dependency_overrides:
|
|||||||
path: ../notifications
|
path: ../notifications
|
||||||
profile:
|
profile:
|
||||||
path: ../profile
|
path: ../profile
|
||||||
|
sf_infrastructure:
|
||||||
|
path: ../../packages/sf_infrastructure
|
||||||
sf_localizations:
|
sf_localizations:
|
||||||
path: ../../packages/sf_localizations
|
path: ../../packages/sf_localizations
|
||||||
sf_shared:
|
sf_shared:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# melos_managed_dependency_overrides: auth,design_system,home,notifications,profile,sf_shared,navigation,utils,sf_localizations,fonts
|
# melos_managed_dependency_overrides: auth,design_system,home,notifications,profile,sf_shared,navigation,utils,sf_localizations,fonts,sf_infrastructure
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
auth:
|
auth:
|
||||||
path: ../auth
|
path: ../auth
|
||||||
@@ -14,6 +14,8 @@ dependency_overrides:
|
|||||||
path: ../notifications
|
path: ../notifications
|
||||||
profile:
|
profile:
|
||||||
path: ../profile
|
path: ../profile
|
||||||
|
sf_infrastructure:
|
||||||
|
path: ../../packages/sf_infrastructure
|
||||||
sf_localizations:
|
sf_localizations:
|
||||||
path: ../../packages/sf_localizations
|
path: ../../packages/sf_localizations
|
||||||
sf_shared:
|
sf_shared:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# melos_managed_dependency_overrides: auth,dashboard_shell,design_system,notifications,profile,sf_shared,navigation,utils,sf_localizations,fonts
|
# melos_managed_dependency_overrides: auth,dashboard_shell,design_system,notifications,profile,sf_shared,navigation,utils,sf_localizations,fonts,sf_infrastructure
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
auth:
|
auth:
|
||||||
path: ../auth
|
path: ../auth
|
||||||
@@ -14,6 +14,8 @@ dependency_overrides:
|
|||||||
path: ../notifications
|
path: ../notifications
|
||||||
profile:
|
profile:
|
||||||
path: ../profile
|
path: ../profile
|
||||||
|
sf_infrastructure:
|
||||||
|
path: ../../packages/sf_infrastructure
|
||||||
sf_localizations:
|
sf_localizations:
|
||||||
path: ../../packages/sf_localizations
|
path: ../../packages/sf_localizations
|
||||||
sf_shared:
|
sf_shared:
|
||||||
|
|||||||
@@ -9,4 +9,5 @@ export 'src/snackbars/snackbar.dart';
|
|||||||
export 'src/buttons/primary_button.dart';
|
export 'src/buttons/primary_button.dart';
|
||||||
export 'src/buttons/secondary_button.dart';
|
export 'src/buttons/secondary_button.dart';
|
||||||
export 'src/buttons/custom_text_button.dart';
|
export 'src/buttons/custom_text_button.dart';
|
||||||
export 'src/dropdowns/dropdown.dart';
|
export 'src/dropdowns/dropdown.dart';
|
||||||
|
export 'src/dropdowns/country_prefix_picker.dart';
|
||||||
|
|||||||
@@ -1,28 +1,27 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class CustomTextButton extends StatelessWidget{
|
class CustomTextButton extends StatelessWidget {
|
||||||
|
final VoidCallback onPressed;
|
||||||
final onPressed;
|
|
||||||
final String text;
|
final String text;
|
||||||
final double size;
|
final double size;
|
||||||
final FontWeight weight;
|
final FontWeight weight;
|
||||||
final Color? color;
|
final Color? color;
|
||||||
|
|
||||||
@override
|
|
||||||
const CustomTextButton({
|
const CustomTextButton({
|
||||||
super.key,
|
super.key,
|
||||||
required this.onPressed,
|
required this.onPressed,
|
||||||
required this.text,
|
required this.text,
|
||||||
this.size = 14,
|
this.size = 14,
|
||||||
this.weight = FontWeight.normal,
|
this.weight = FontWeight.normal,
|
||||||
this.color
|
this.color,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return TextButton(
|
return TextButton(
|
||||||
style: ButtonStyle(padding: WidgetStatePropertyAll(EdgeInsets.zero)),
|
style: const ButtonStyle(
|
||||||
|
padding: WidgetStatePropertyAll<EdgeInsetsGeometry>(EdgeInsets.zero),
|
||||||
|
),
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
child: Text(
|
child: Text(
|
||||||
text,
|
text,
|
||||||
@@ -30,10 +29,10 @@ class CustomTextButton extends StatelessWidget{
|
|||||||
fontSize: size,
|
fontSize: size,
|
||||||
fontWeight: weight,
|
fontWeight: weight,
|
||||||
letterSpacing: 0,
|
letterSpacing: 0,
|
||||||
color: color?? Color(0xFF4B4B4B),
|
color: color ?? const Color(0xFF4B4B4B),
|
||||||
decoration: TextDecoration.underline
|
decoration: TextDecoration.underline,
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import 'package:design_system/design_system.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
|
|
||||||
class PrimaryButton extends StatelessWidget{
|
class PrimaryButton extends StatelessWidget {
|
||||||
final onPressed;
|
final VoidCallback onPressed;
|
||||||
final String text;
|
final String text;
|
||||||
final Color color;
|
final Color color;
|
||||||
final double height;
|
final double height;
|
||||||
@@ -12,7 +10,8 @@ class PrimaryButton extends StatelessWidget{
|
|||||||
final double radius;
|
final double radius;
|
||||||
final double padding;
|
final double padding;
|
||||||
|
|
||||||
PrimaryButton({
|
const PrimaryButton({
|
||||||
|
super.key,
|
||||||
required this.onPressed,
|
required this.onPressed,
|
||||||
required this.text,
|
required this.text,
|
||||||
required this.color,
|
required this.color,
|
||||||
@@ -25,30 +24,35 @@ class PrimaryButton extends StatelessWidget{
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return FilledButton(
|
return FilledButton(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
backgroundColor: WidgetStatePropertyAll<Color>(color),
|
backgroundColor: WidgetStatePropertyAll<Color>(color),
|
||||||
padding: WidgetStatePropertyAll(EdgeInsets.symmetric(horizontal: padding)),
|
padding: WidgetStatePropertyAll<EdgeInsetsGeometry>(
|
||||||
shape: WidgetStatePropertyAll(RoundedRectangleBorder(
|
EdgeInsets.symmetric(horizontal: padding),
|
||||||
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
),
|
||||||
)),
|
shape: WidgetStatePropertyAll<OutlinedBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
child: Center(child: Text(
|
child: Center(
|
||||||
text,
|
child: Text(
|
||||||
textAlign: TextAlign.center,
|
text,
|
||||||
style: TextStyle(
|
textAlign: TextAlign.center,
|
||||||
fontSize: size,
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w500,
|
fontSize: size,
|
||||||
letterSpacing: 0,
|
fontWeight: FontWeight.w500,
|
||||||
color: Colors.white//theme.getColorFor(ThemeCode.textSecondary)
|
letterSpacing: 0,
|
||||||
)
|
color: Colors.white, // theme.getColorFor(ThemeCode.textSecondary)
|
||||||
))
|
),
|
||||||
)
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import 'package:design_system/design_system.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
|
|
||||||
class SecondaryButton extends StatelessWidget {
|
class SecondaryButton extends StatelessWidget {
|
||||||
|
final VoidCallback onPressed;
|
||||||
final onPressed;
|
|
||||||
final String? text;
|
final String? text;
|
||||||
final IconData? icon;
|
final IconData? icon;
|
||||||
final String? label;
|
final String? label;
|
||||||
@@ -15,8 +12,8 @@ class SecondaryButton extends StatelessWidget {
|
|||||||
final double? width;
|
final double? width;
|
||||||
final double? size;
|
final double? size;
|
||||||
|
|
||||||
@override
|
const SecondaryButton({
|
||||||
SecondaryButton({
|
super.key,
|
||||||
required this.onPressed,
|
required this.onPressed,
|
||||||
this.text,
|
this.text,
|
||||||
this.icon,
|
this.icon,
|
||||||
@@ -31,37 +28,43 @@ class SecondaryButton extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return OutlinedButton(
|
return OutlinedButton(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
padding: WidgetStatePropertyAll(EdgeInsets.symmetric(horizontal: padding)),
|
padding: WidgetStatePropertyAll(
|
||||||
shape: WidgetStatePropertyAll(RoundedRectangleBorder(
|
EdgeInsets.symmetric(horizontal: padding),
|
||||||
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
),
|
||||||
side: BorderSide(color: Color(0xFF4B4B4B))
|
shape: WidgetStatePropertyAll(
|
||||||
)),
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
||||||
|
side: BorderSide(color: Color(0xFF4B4B4B)),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
child: Center(child: text!=null ? Text(
|
child: Center(
|
||||||
text!,
|
child: text != null
|
||||||
textAlign: TextAlign.center,
|
? Text(
|
||||||
semanticsLabel: label,
|
text!,
|
||||||
style: TextStyle(
|
textAlign: TextAlign.center,
|
||||||
fontSize: size ?? 18,
|
semanticsLabel: label,
|
||||||
fontWeight: FontWeight.w500,
|
style: TextStyle(
|
||||||
letterSpacing: 0,
|
fontSize: size ?? 18,
|
||||||
color: Color(0xFF4B4B4B)
|
fontWeight: FontWeight.w500,
|
||||||
)
|
letterSpacing: 0,
|
||||||
) : Icon(
|
color: Color(0xFF4B4B4B),
|
||||||
icon,
|
),
|
||||||
semanticLabel: label,
|
)
|
||||||
size: size ?? 24,
|
: Icon(
|
||||||
color: color ?? Color(0xFF4B4B4B)
|
icon,
|
||||||
))
|
semanticLabel: label,
|
||||||
)
|
size: size ?? 24,
|
||||||
|
color: color ?? Color(0xFF4B4B4B),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import 'package:country_code_picker/country_code_picker.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CountryPrefixPicker extends StatelessWidget {
|
||||||
|
const CountryPrefixPicker({
|
||||||
|
super.key,
|
||||||
|
required this.onChanged,
|
||||||
|
this.initialCountryCode = '+34',
|
||||||
|
this.radius = 12,
|
||||||
|
this.width = 90,
|
||||||
|
this.height = 55,
|
||||||
|
this.borderColor = const Color(0xFF4B4B4B),
|
||||||
|
this.backgroundColor = Colors.white,
|
||||||
|
});
|
||||||
|
|
||||||
|
final ValueChanged<CountryCode> onChanged;
|
||||||
|
final String initialCountryCode;
|
||||||
|
|
||||||
|
final double radius;
|
||||||
|
final double width;
|
||||||
|
final double height;
|
||||||
|
final Color borderColor;
|
||||||
|
final Color backgroundColor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
child: CountryCodePicker(
|
||||||
|
onChanged: onChanged,
|
||||||
|
initialSelection: initialCountryCode,
|
||||||
|
showFlag: false,
|
||||||
|
showDropDownButton: false,
|
||||||
|
hideMainText: true,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
builder: (CountryCode? country) {
|
||||||
|
if (country == null) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
return InputDecorator(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
isDense: false,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 16,
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor: backgroundColor,
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
||||||
|
borderSide: BorderSide(color: borderColor),
|
||||||
|
),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
||||||
|
borderSide: BorderSide(color: borderColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
if (country.flagUri != null)
|
||||||
|
Image.asset(
|
||||||
|
country.flagUri!,
|
||||||
|
package: 'country_code_picker',
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
const Icon(Icons.arrow_drop_down, size: 24),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
import 'package:design_system/design_system.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
|
|
||||||
class CustomDropdown extends StatelessWidget{
|
class CustomDropdown extends StatelessWidget {
|
||||||
final List<Widget> items;
|
final List<Widget> items;
|
||||||
final values;
|
final List<dynamic>? values;
|
||||||
final onChanged;
|
final ValueChanged<dynamic> onChanged;
|
||||||
final value;
|
final dynamic value;
|
||||||
final String? hint;
|
final String? hint;
|
||||||
final String? label;
|
final String? label;
|
||||||
final double radius;
|
final double radius;
|
||||||
@@ -25,43 +23,54 @@ class CustomDropdown extends StatelessWidget{
|
|||||||
this.radius = 12,
|
this.radius = 12,
|
||||||
this.width = double.infinity,
|
this.width = double.infinity,
|
||||||
this.height = 70,
|
this.height = 70,
|
||||||
this.color
|
this.color,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
if (label != null) Align(
|
if (label != null)
|
||||||
alignment: Alignment.bottomLeft,
|
Align(
|
||||||
child: Text(
|
alignment: Alignment.bottomLeft,
|
||||||
label!,
|
child: Text(
|
||||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
label!,
|
||||||
|
style: const TextStyle(fontSize: 14, letterSpacing: 0),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
child: Center(child: DropdownButtonFormField(
|
child: Center(
|
||||||
dropdownColor: Colors.white,
|
child: DropdownButtonFormField<dynamic>(
|
||||||
decoration: InputDecoration(
|
dropdownColor: Colors.white,
|
||||||
enabledBorder: OutlineInputBorder(
|
decoration: InputDecoration(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: color??Color(0xFF4B4B4B))
|
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
||||||
)
|
borderSide: BorderSide(
|
||||||
|
color: color ?? const Color(0xFF4B4B4B),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
initialValue: value,
|
||||||
|
onChanged: onChanged,
|
||||||
|
hint: hint != null ? Text(hint!) : null,
|
||||||
|
items: List<DropdownMenuItem<dynamic>>.generate(items.length, (
|
||||||
|
int index,
|
||||||
|
) {
|
||||||
|
final dynamic itemValue = values != null
|
||||||
|
? values![index]
|
||||||
|
: index;
|
||||||
|
return DropdownMenuItem<dynamic>(
|
||||||
|
value: itemValue,
|
||||||
|
child: items[index],
|
||||||
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
//underline: Container(),
|
),
|
||||||
initialValue: value,
|
),
|
||||||
onChanged: onChanged,
|
|
||||||
hint: Text(hint??""),
|
|
||||||
items: List<DropdownMenuItem>.generate(items.length, (int index){
|
|
||||||
return DropdownMenuItem(value: (values!=null)?values[index]:index, child: items[index]);
|
|
||||||
})
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
) ;
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
import 'package:design_system/design_system.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
|
|
||||||
class CustomTextField extends StatefulWidget{
|
class CustomTextField extends StatefulWidget {
|
||||||
bool? showPassword;
|
final bool? showPassword;
|
||||||
final bool numeric;
|
final bool numeric;
|
||||||
final String hint;
|
final String hint;
|
||||||
final String label;
|
final String label;
|
||||||
final int? lines;
|
final int? lines;
|
||||||
final ValueChanged<String>? onChanged;
|
final ValueChanged<String>? onChanged;
|
||||||
final int? length;
|
final int? length;
|
||||||
|
final TextEditingController? controller;
|
||||||
|
|
||||||
CustomTextField({
|
const CustomTextField({
|
||||||
super.key,
|
super.key,
|
||||||
this.showPassword,
|
this.showPassword,
|
||||||
this.numeric = false,
|
this.numeric = false,
|
||||||
@@ -21,63 +20,72 @@ class CustomTextField extends StatefulWidget{
|
|||||||
this.lines,
|
this.lines,
|
||||||
this.length,
|
this.length,
|
||||||
this.onChanged,
|
this.onChanged,
|
||||||
|
this.controller,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CustomTextField> createState() => CustomTextFieldState();
|
State<CustomTextField> createState() => CustomTextFieldState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class CustomTextFieldState extends State<CustomTextField>{
|
class CustomTextFieldState extends State<CustomTextField> {
|
||||||
|
late bool _showPassword;
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_showPassword = widget.showPassword ?? true;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
?widget.label == '' ? null : Align(
|
if (widget.label.isNotEmpty)
|
||||||
alignment: Alignment.bottomLeft,
|
Align(
|
||||||
child: Text(
|
alignment: Alignment.bottomLeft,
|
||||||
widget.label,
|
child: Text(
|
||||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
widget.label,
|
||||||
)
|
style: const TextStyle(fontSize: 14, letterSpacing: 0),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
keyboardType: widget.numeric? TextInputType.number : TextInputType.text,
|
keyboardType: widget.numeric
|
||||||
obscureText: !(widget.showPassword ?? true),
|
? TextInputType.number
|
||||||
enableSuggestions: widget.showPassword ?? true,
|
: TextInputType.text,
|
||||||
autocorrect: !(widget.showPassword ?? false),
|
obscureText: !_showPassword,
|
||||||
style: TextStyle(color: Color(0xFF4B4B4B)),
|
enableSuggestions: _showPassword,
|
||||||
inputFormatters: widget.numeric? [
|
autocorrect: !_showPassword,
|
||||||
FilteringTextInputFormatter.digitsOnly
|
style: const TextStyle(color: Color(0xFF4B4B4B)),
|
||||||
] : [],
|
inputFormatters: widget.numeric
|
||||||
|
? <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly]
|
||||||
|
: const <TextInputFormatter>[],
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
counterText: "",
|
counterText: "",
|
||||||
hintText: widget.hint,
|
hintText: widget.hint,
|
||||||
//labelText: widget.label,
|
border: const OutlineInputBorder(
|
||||||
//floatingLabelBehavior: FloatingLabelBehavior.always,
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||||
borderSide: BorderSide(color: Color(0xFF4B4B4B)),
|
borderSide: BorderSide(color: Color(0xFF4B4B4B)),
|
||||||
gapPadding: 16
|
gapPadding: 16,
|
||||||
),
|
),
|
||||||
suffixIcon: widget.showPassword!=null ? IconButton(
|
suffixIcon: widget.showPassword != null
|
||||||
icon: Icon(widget.showPassword!
|
? IconButton(
|
||||||
? Icons.visibility_off
|
icon: Icon(
|
||||||
: Icons.visibility),
|
_showPassword ? Icons.visibility_off : Icons.visibility,
|
||||||
onPressed: () {
|
),
|
||||||
setState(() {
|
onPressed: () {
|
||||||
widget.showPassword = !widget.showPassword!;
|
setState(() {
|
||||||
});
|
_showPassword = !_showPassword;
|
||||||
},
|
});
|
||||||
) : null,
|
},
|
||||||
|
)
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
minLines: widget.lines ?? 1,
|
minLines: widget.lines ?? 1,
|
||||||
maxLines: widget.lines ?? 1,
|
maxLines: widget.lines ?? 1,
|
||||||
maxLength: widget.length,
|
maxLength: widget.length,
|
||||||
onChanged: widget.onChanged ?? (_)=>{},
|
onChanged: widget.onChanged,
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
|
|
||||||
class ProgressBar extends ConsumerWidget{
|
class ProgressBar extends StatelessWidget {
|
||||||
final double max;
|
final double max;
|
||||||
final double value;
|
final double value;
|
||||||
final double height;
|
final double height;
|
||||||
@@ -13,6 +12,7 @@ class ProgressBar extends ConsumerWidget{
|
|||||||
final Color textColor;
|
final Color textColor;
|
||||||
|
|
||||||
const ProgressBar({
|
const ProgressBar({
|
||||||
|
super.key,
|
||||||
required this.max,
|
required this.max,
|
||||||
required this.value,
|
required this.value,
|
||||||
required this.height,
|
required this.height,
|
||||||
@@ -20,21 +20,19 @@ class ProgressBar extends ConsumerWidget{
|
|||||||
required this.textSecondarySize,
|
required this.textSecondarySize,
|
||||||
required this.backgroundColor,
|
required this.backgroundColor,
|
||||||
required this.foregroundColor,
|
required this.foregroundColor,
|
||||||
required this.textColor,}
|
required this.textColor,
|
||||||
);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(
|
||||||
return
|
children: [
|
||||||
Stack(
|
LinearProgressIndicator(
|
||||||
children: [
|
|
||||||
LinearProgressIndicator(
|
|
||||||
value: value / max,
|
value: value / max,
|
||||||
minHeight: height,
|
minHeight: height,
|
||||||
borderRadius: BorderRadius.all(Radius.circular(24)),
|
borderRadius: BorderRadius.all(Radius.circular(24)),
|
||||||
color: foregroundColor,
|
color: foregroundColor,
|
||||||
backgroundColor: backgroundColor
|
backgroundColor: backgroundColor,
|
||||||
),
|
),
|
||||||
FractionallySizedBox(
|
FractionallySizedBox(
|
||||||
widthFactor: value / max,
|
widthFactor: value / max,
|
||||||
@@ -47,10 +45,10 @@ class ProgressBar extends ConsumerWidget{
|
|||||||
secondarySize: textSecondarySize,
|
secondarySize: textSecondarySize,
|
||||||
color: textColor,
|
color: textColor,
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,20 @@
|
|||||||
import 'package:design_system/design_system.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
|
|
||||||
enum MessageType {
|
enum MessageType { info, error, warning, success }
|
||||||
info,
|
|
||||||
error,
|
|
||||||
warning,
|
|
||||||
success
|
|
||||||
}
|
|
||||||
|
|
||||||
class CustomSnackBar extends StatelessWidget{
|
class CustomSnackBar extends StatelessWidget {
|
||||||
final MessageType? type;
|
final MessageType? type;
|
||||||
final String message;
|
final String message;
|
||||||
|
|
||||||
const CustomSnackBar({
|
const CustomSnackBar({super.key, this.type, required this.message});
|
||||||
super.key,
|
|
||||||
this.type,
|
|
||||||
required this.message,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
SnackBar build(BuildContext context) {
|
SnackBar build(BuildContext context) {
|
||||||
|
|
||||||
late final Color foregroundColor;
|
late final Color foregroundColor;
|
||||||
late final Color backgroundColor;
|
late final Color backgroundColor;
|
||||||
late final IconData icon;
|
late final IconData icon;
|
||||||
|
|
||||||
switch (type??MessageType.info){
|
switch (type ?? MessageType.info) {
|
||||||
case MessageType.info:
|
case MessageType.info:
|
||||||
backgroundColor = Color(0xFFE3EFFD);
|
backgroundColor = Color(0xFFE3EFFD);
|
||||||
foregroundColor = Color(0xFF1F4ECF);
|
foregroundColor = Color(0xFF1F4ECF);
|
||||||
@@ -50,15 +38,20 @@ class CustomSnackBar extends StatelessWidget{
|
|||||||
backgroundColor: backgroundColor,
|
backgroundColor: backgroundColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
side: BorderSide(color: foregroundColor, width: 1),
|
side: BorderSide(color: foregroundColor, width: 1),
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10))
|
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||||
),
|
),
|
||||||
content: Row(
|
content: Row(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
Icon(icon, color: foregroundColor),
|
Icon(icon, color: foregroundColor),
|
||||||
Expanded(child: Text(message, style: TextStyle(color: Color(0xFF4B4B4B), fontSize: 14)))
|
Expanded(
|
||||||
],
|
child: Text(
|
||||||
),
|
message,
|
||||||
|
style: TextStyle(color: Color(0xFF4B4B4B), fontSize: 14),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class StepIndicator extends StatelessWidget{
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: isActive ? color : Colors.white,
|
color: isActive ? color : Colors.white,
|
||||||
border: Border.all(color: color, width: 2),
|
border: Border.all(color: color),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ dependencies:
|
|||||||
path: ../utils
|
path: ../utils
|
||||||
flutter_riverpod: ^3.0.3
|
flutter_riverpod: ^3.0.3
|
||||||
get_it: ^9.0.5
|
get_it: ^9.0.5
|
||||||
|
country_code_picker: ^3.4.1
|
||||||
fonts:
|
fonts:
|
||||||
path: ../../packages/fonts
|
path: ../../packages/fonts
|
||||||
|
|
||||||
|
|||||||
BIN
packages/design_system/test/goldens/dropdown.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
packages/design_system/test/goldens/money_text.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
packages/design_system/test/goldens/primary_button.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
packages/design_system/test/goldens/progress_bar_large.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
packages/design_system/test/goldens/progress_bar_small.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
packages/design_system/test/goldens/secondary_button.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
packages/design_system/test/goldens/snackbar/default.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
packages/design_system/test/goldens/snackbar/default_empty.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
BIN
packages/design_system/test/goldens/snackbar/error.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
packages/design_system/test/goldens/snackbar/error_empty.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
packages/design_system/test/goldens/snackbar/error_long_text.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
packages/design_system/test/goldens/snackbar/info.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
packages/design_system/test/goldens/snackbar/info_empty.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
packages/design_system/test/goldens/snackbar/info_long_text.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
packages/design_system/test/goldens/snackbar/success.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
packages/design_system/test/goldens/snackbar/success_empty.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
BIN
packages/design_system/test/goldens/snackbar/warning.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
packages/design_system/test/goldens/snackbar/warning_empty.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 6.7 KiB |