Merge pull request 'feat(auth,sf_infrastructure): register QuestiaApi/Dio and connect link_phone remote datasource' (#7) from feature/auth-link-phone into develop

Reviewed-on: #7
This commit was merged in pull request #7.
This commit is contained in:
2025-12-04 15:13:41 +00:00
88 changed files with 2300 additions and 393 deletions

31
packages/sf_infrastructure/.gitignore vendored Normal file
View File

@@ -0,0 +1,31 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.flutter-plugins-dependencies
/build/
/coverage/

View File

@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2"
channel: "stable"
project_type: package

View File

@@ -0,0 +1,3 @@
## 0.0.1
* TODO: Describe initial release.

View File

@@ -0,0 +1 @@
TODO: Add your license here.

View File

@@ -0,0 +1,39 @@
<!--
This README describes the package. If you publish this package to pub.dev,
this README's contents appear on the landing page for your package.
For information about how to write a good package README, see the guide for
[writing package pages](https://dart.dev/tools/pub/writing-package-pages).
For general information about developing packages, see the Dart guide for
[creating packages](https://dart.dev/guides/libraries/create-packages)
and the Flutter guide for
[developing packages and plugins](https://flutter.dev/to/develop-packages).
-->
TODO: Put a short description of the package here that helps potential users
know whether this package might be useful for them.
## Features
TODO: List what your package can do. Maybe include images, gifs, or videos.
## Getting started
TODO: List prerequisites and provide or point to information on how to
start using the package.
## Usage
TODO: Include short and useful examples for package users. Add longer examples
to `/example` folder.
```dart
const like = 'sample';
```
## Additional information
TODO: Tell users more about the package: where to find more information, how to
contribute to the package, how to file issues, what response they can expect
from the package authors, and more.

View File

@@ -0,0 +1,4 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

View File

@@ -0,0 +1,26 @@
import 'package:dio/dio.dart';
import 'package:get_it/get_it.dart';
import 'src/network/dio_client.dart';
import 'src/env/env_contract.dart';
import 'src/api/questia_api.dart';
import 'src/repositories/questia_repository_impl.dart';
import 'src/repositories/questia_repository.dart';
export 'src/repositories/questia_repository.dart';
final getIt = GetIt.instance;
Future<void> configureDependencies(EnvConfig env, {bool log = false}) async {
getIt.registerLazySingleton<Dio>(
() => buildDioClient(
baseUrl: env.apiBaseUrl,
// apiKey: env.apiKey,
log: log,
),
);
getIt.registerLazySingleton<QuestiaApi>(() => QuestiaApi(getIt<Dio>()));
getIt.registerLazySingleton<QuestiaRepository>(
() => QuestiaRepositoryImpl(getIt<QuestiaApi>()),
);
}

View File

@@ -0,0 +1,2 @@
export 'src/env/env_contract.dart';
export 'configure_dependencies.dart';

View File

@@ -0,0 +1,79 @@
import 'package:dio/dio.dart';
class QuestiaApi {
final Dio _dio;
QuestiaApi(this._dio);
Future<Response<T>> get<T>(
String path, {
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onReceiveProgress,
}) {
return _dio.get<T>(
path,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress,
);
}
Future<Response<T>> post<T>(
String path, {
dynamic data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) {
return _dio.post<T>(
path,
data: data,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
Future<Response<T>> put<T>(
String path, {
dynamic data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) {
return _dio.put<T>(
path,
data: data,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
Future<Response<T>> delete<T>(
String path, {
dynamic data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
}) {
return _dio.delete<T>(
path,
data: data,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
);
}
}

View File

@@ -0,0 +1,4 @@
abstract class EnvConfig {
String get apiBaseUrl;
// String get apiKey;
}

View File

@@ -0,0 +1,36 @@
import 'package:dio/dio.dart';
Dio buildDioClient({
required String baseUrl,
// required String apiKey,
bool log = false,
}) {
final dio = Dio(
BaseOptions(
baseUrl: baseUrl,
connectTimeout: const Duration(seconds: 20),
receiveTimeout: const Duration(seconds: 20),
sendTimeout: const Duration(seconds: 20),
headers: {
// if (apiKey.isNotEmpty) 'x-api-key': apiKey,
'accept': 'application/json',
'content-type': 'application/json',
},
),
);
if (log) {
dio.interceptors.add(
LogInterceptor(
request: true,
requestHeader: false,
requestBody: true,
responseHeader: false,
responseBody: true,
error: true,
),
);
}
return dio;
}

View File

@@ -0,0 +1,26 @@
import 'package:dio/dio.dart';
abstract class QuestiaRepository {
Future<Response<T>> get<T>(
String path, {
Map<String, dynamic>? queryParameters,
});
Future<Response<T>> post<T>(
String path, {
dynamic body,
Map<String, dynamic>? queryParameters,
});
Future<Response<T>> put<T>(
String path, {
dynamic body,
Map<String, dynamic>? queryParameters,
});
Future<Response<T>> delete<T>(
String path, {
dynamic body,
Map<String, dynamic>? queryParameters,
});
}

View File

@@ -0,0 +1,45 @@
import 'package:dio/dio.dart';
import '../api/questia_api.dart';
import 'questia_repository.dart';
class QuestiaRepositoryImpl implements QuestiaRepository {
final QuestiaApi _api;
QuestiaRepositoryImpl(this._api);
@override
Future<Response<T>> get<T>(
String path, {
Map<String, dynamic>? queryParameters,
}) {
return _api.get<T>(path, queryParameters: queryParameters);
}
@override
Future<Response<T>> post<T>(
String path, {
dynamic body,
Map<String, dynamic>? queryParameters,
}) {
return _api.post<T>(path, data: body, queryParameters: queryParameters);
}
@override
Future<Response<T>> put<T>(
String path, {
dynamic body,
Map<String, dynamic>? queryParameters,
}) {
return _api.put<T>(path, data: body, queryParameters: queryParameters);
}
@override
Future<Response<T>> delete<T>(
String path, {
dynamic body,
Map<String, dynamic>? queryParameters,
}) {
return _api.delete<T>(path, data: body, queryParameters: queryParameters);
}
}

View File

@@ -0,0 +1,56 @@
name: sf_infrastructure
description: "A new Flutter package project."
version: 0.0.1
homepage:
environment:
sdk: ^3.9.2
flutter: ">=1.17.0"
dependencies:
dio: ^5.9.0
flutter:
sdk: flutter
get_it: ^9.0.5
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^5.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# To add assets to your package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.dev/to/asset-from-package
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/to/resolution-aware-images
# To add custom fonts to your package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.dev/to/font-from-package

View File

@@ -8,5 +8,9 @@
"onboardingTitle2": "Gelassenheit bei jeder Zahlung",
"onboardingSubtitle2": "Überwache ihre Ausgaben, setze Limits und begleite sie bei jedem Schritt",
"onboardingTitle3": "Einfache und sichere Zahlungen in ihren Händen",
"onboardingSubtitle3": "Sie können mit ihrer Uhr bezahlen.\nGanz ohne Handy und Bargeld"
"onboardingSubtitle3": "Sie können mit ihrer Uhr bezahlen.\nGanz ohne Handy und Bargeld",
"linkPhoneTitle": "Wir freuen uns sehr, dass du hier bist!",
"linkPhoneSubtitle": "Um dich sicher anzumelden, senden wir dir einen Code an deine Telefonnummer",
"mobilePhone": "Mobiltelefon",
"phoneNumber": "Telefonnummer"
}

View File

@@ -8,5 +8,9 @@
"onboardingSubtitle3": "They can pay from their watch.\nNo phone or cash needed",
"start": "Start",
"next": "Next",
"skip": "Skip"
"skip": "Skip",
"linkPhoneTitle": "We're really happy to have you here!",
"linkPhoneSubtitle": "To sign in securely, we'll send a code to your phone number",
"mobilePhone": "Mobile phone",
"phoneNumber": "Phone number"
}

View File

@@ -8,5 +8,9 @@
"onboardingSubtitle3": "Podrá pagar desde su reloj.\nSin móvil ni efectivo",
"start": "Comenzar",
"next": "Siguiente",
"skip": "Omitir"
"skip": "Omitir",
"linkPhoneTitle": "¡Nos alegra mucho tenerte por aquí!",
"linkPhoneSubtitle": "Para poder entrar de forma segura, te vamos a enviar un código al teléfono",
"mobilePhone": "Teléfono móvil",
"phoneNumber": "Teléfono"
}

View File

@@ -8,5 +8,9 @@
"onboardingTitle2": "La tranquillité à chaque paiement",
"onboardingSubtitle2": "Surveillez leurs dépenses, fixez des limites et accompagnez-les à chaque étape",
"onboardingTitle3": "Des paiements faciles et sécurisés entre leurs mains",
"onboardingSubtitle3": "Ils peuvent payer avec leur montre.\nSans téléphone ni espèces"
"onboardingSubtitle3": "Ils peuvent payer avec leur montre.\nSans téléphone ni espèces",
"linkPhoneTitle": "Nous sommes ravis de te compter parmi nous !",
"linkPhoneSubtitle": "Pour te connecter en toute sécurité, nous allons envoyer un code sur ton téléphone",
"mobilePhone": "Téléphone portable",
"phoneNumber": "Numéro de téléphone"
}

View File

@@ -8,5 +8,9 @@
"onboardingTitle2": "Tranquillità in ogni pagamento",
"onboardingSubtitle2": "Monitora le sue spese, imposta limiti e accompagnalo in ogni passo",
"onboardingTitle3": "Pagamenti facili e sicuri nelle sue mani",
"onboardingSubtitle3": "Potrà pagare dal suo orologio.\nSenza telefono né contanti"
"onboardingSubtitle3": "Potrà pagare dal suo orologio.\nSenza telefono né contanti",
"linkPhoneTitle": "Siamo molto felici di averti qui!",
"linkPhoneSubtitle": "Per accedere in modo sicuro, ti invieremo un codice al tuo telefono",
"mobilePhone": "Telefono cellulare",
"phoneNumber": "Numero di telefono"
}

View File

@@ -8,5 +8,9 @@
"onboardingTitle2": "Tranquilidade em cada pagamento",
"onboardingSubtitle2": "Monitore os gastos deles, defina limites e acompanhe cada passo",
"onboardingTitle3": "Pagamentos fáceis e seguros nas mãos deles",
"onboardingSubtitle3": "Eles poderão pagar pelo relógio.\nSem celular nem dinheiro em espécie"
"onboardingSubtitle3": "Eles poderão pagar pelo relógio.\nSem celular nem dinheiro em espécie",
"linkPhoneTitle": "Ficamos muito felizes em ter você aqui!",
"linkPhoneSubtitle": "Para entrar com segurança, vamos enviar um código para o seu telefone",
"mobilePhone": "Telefone celular",
"phoneNumber": "Número de telefone"
}

View File

@@ -13,4 +13,8 @@ class I18n {
static const String onboardingSubtitle2 = 'onboardingSubtitle2';
static const String onboardingTitle3 = 'onboardingTitle3';
static const String onboardingSubtitle3 = 'onboardingSubtitle3';
static const String linkPhoneTitle = 'linkPhoneTitle';
static const String linkPhoneSubtitle = 'linkPhoneSubtitle';
static const String mobilePhone = 'mobilePhone';
static const String phoneNumber = 'phoneNumber';
}