Integration fonctionnalités V1 ( resas + gestion machines

This commit is contained in:
bastien
2026-07-03 19:02:48 +02:00
parent 20f383dd62
commit bf191d6396
46 changed files with 4691 additions and 654 deletions
+33 -3
View File
@@ -2,6 +2,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../api/api_client.dart';
import '../config/app_config.dart';
import '../config/secure_storage_config.dart';
import '../../features/auth/domain/auth_user.dart';
import 'auth_repository.dart';
@@ -44,12 +45,33 @@ class AuthState {
/// Gestionnaire d'état Riverpod pour l'authentification.
class AuthNotifier extends StateNotifier<AuthState> {
AuthNotifier(this._repository) : super(const AuthState()) {
AuthNotifier(this._repository) : super(const AuthState(isLoading: true)) {
_restoreSession();
}
final AuthRepository _repository;
/// Tente de renouveler le token d'accès (appelé par le client API sur 401).
Future<String?> refreshAccessToken() async {
final refreshed = await _repository.refresh();
if (refreshed == null) {
return null;
}
state = state.copyWith(
accessToken: refreshed.accessToken,
refreshToken: refreshed.refreshToken,
user: refreshed.user ?? state.user,
);
return refreshed.accessToken;
}
/// Session expirée après échec du refresh.
Future<void> sessionExpired() async {
await logout();
}
Future<void> _restoreSession() async {
state = state.copyWith(isLoading: true, clearError: true);
@@ -149,8 +171,16 @@ class AuthNotifier extends StateNotifier<AuthState> {
}
final authRepositoryProvider = Provider<AuthRepository>((ref) {
// Client dédié à l'auth pour éviter une dépendance circulaire avec apiClientProvider.
return AuthRepository(apiClient: ApiClient(baseUrl: kApiBaseUrl));
final storage = laverieSecureStorage;
// Token lu depuis le stockage sécurisé (évite la dépendance circulaire avec authProvider).
return AuthRepository(
apiClient: ApiClient(
baseUrl: kApiBaseUrl,
getAccessToken: () => storage.read(key: AuthStorageKeys.accessToken),
),
secureStorage: storage,
);
});
final authProvider = StateNotifierProvider<AuthNotifier, AuthState>((ref) {
+9 -10
View File
@@ -2,6 +2,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import '../api/api_client.dart';
import '../api/api_endpoints.dart';
import '../api/api_response.dart';
import '../config/app_config.dart';
import '../config/secure_storage_config.dart';
import '../../features/auth/domain/auth_user.dart';
@@ -29,7 +30,7 @@ class AuthRepository {
},
);
final tokens = AuthTokens.fromJson(response.data as Map<String, dynamic>);
final tokens = AuthTokens.fromJson(ApiResponse.payload(response.data));
await _persistTokens(tokens);
return tokens;
}
@@ -52,7 +53,7 @@ class AuthRepository {
},
);
final tokens = AuthTokens.fromJson(response.data as Map<String, dynamic>);
final tokens = AuthTokens.fromJson(ApiResponse.payload(response.data));
await _persistTokens(tokens);
return tokens;
}
@@ -68,23 +69,21 @@ class AuthRepository {
data: {'refresh_token': refreshToken},
);
final tokens = AuthTokens.fromJson(response.data as Map<String, dynamic>);
final tokens = AuthTokens.fromJson(ApiResponse.payload(response.data));
await _persistTokens(tokens);
return tokens;
}
Future<AuthUser?> fetchCurrentUser() async {
final response = await _apiClient.get(ApiEndpoints.authMe);
final data = response.data;
final payload = ApiResponse.payload(response.data);
final userJson = payload['user'] as Map<String, dynamic>?;
if (data is Map<String, dynamic>) {
if (data.containsKey('data')) {
return AuthUser.fromJson(data['data'] as Map<String, dynamic>);
}
return AuthUser.fromJson(data);
if (userJson != null) {
return AuthUser.fromJson(userJson);
}
return null;
return AuthUser.fromJson(payload);
}
Future<void> logout() async {