update api

This commit is contained in:
Phuoc Nguyen
2025-10-10 17:15:40 +07:00
parent b94c158004
commit 04f7042b8d
24 changed files with 3322 additions and 8 deletions

View File

@@ -0,0 +1,215 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../../../core/di/injection_container.dart';
import '../../domain/entities/user.dart';
import '../../domain/repositories/auth_repository.dart';
part 'auth_provider.g.dart';
/// Provider for AuthRepository
@riverpod
AuthRepository authRepository(Ref ref) {
return sl<AuthRepository>();
}
/// Auth state class
class AuthState {
final User? user;
final bool isAuthenticated;
final bool isLoading;
final String? errorMessage;
const AuthState({
this.user,
this.isAuthenticated = false,
this.isLoading = false,
this.errorMessage,
});
AuthState copyWith({
User? user,
bool? isAuthenticated,
bool? isLoading,
String? errorMessage,
}) {
return AuthState(
user: user ?? this.user,
isAuthenticated: isAuthenticated ?? this.isAuthenticated,
isLoading: isLoading ?? this.isLoading,
errorMessage: errorMessage ?? this.errorMessage,
);
}
}
/// Auth state notifier provider
@riverpod
class Auth extends _$Auth {
@override
AuthState build() {
_checkAuthStatus();
return const AuthState();
}
AuthRepository get _repository => ref.read(authRepositoryProvider);
/// Check if user is authenticated on app start
Future<void> _checkAuthStatus() async {
state = state.copyWith(isLoading: true);
final isAuthenticated = await _repository.isAuthenticated();
if (isAuthenticated) {
// Get user profile
final result = await _repository.getProfile();
result.fold(
(failure) {
state = const AuthState(
isAuthenticated: false,
isLoading: false,
);
},
(user) {
state = AuthState(
user: user,
isAuthenticated: true,
isLoading: false,
);
},
);
} else {
state = const AuthState(
isAuthenticated: false,
isLoading: false,
);
}
}
/// Login user
Future<bool> login({
required String email,
required String password,
}) async {
state = state.copyWith(isLoading: true, errorMessage: null);
final result = await _repository.login(email: email, password: password);
return result.fold(
(failure) {
state = state.copyWith(
isLoading: false,
errorMessage: failure.message,
);
return false;
},
(authResponse) {
state = AuthState(
user: authResponse.user,
isAuthenticated: true,
isLoading: false,
errorMessage: null,
);
return true;
},
);
}
/// Register new user
Future<bool> register({
required String name,
required String email,
required String password,
List<String> roles = const ['user'],
}) async {
state = state.copyWith(isLoading: true, errorMessage: null);
final result = await _repository.register(
name: name,
email: email,
password: password,
roles: roles,
);
return result.fold(
(failure) {
state = state.copyWith(
isLoading: false,
errorMessage: failure.message,
);
return false;
},
(authResponse) {
state = AuthState(
user: authResponse.user,
isAuthenticated: true,
isLoading: false,
errorMessage: null,
);
return true;
},
);
}
/// Get user profile (refresh user data)
Future<void> getProfile() async {
state = state.copyWith(isLoading: true, errorMessage: null);
final result = await _repository.getProfile();
result.fold(
(failure) {
state = state.copyWith(
isLoading: false,
errorMessage: failure.message,
);
},
(user) {
state = state.copyWith(
user: user,
isLoading: false,
);
},
);
}
/// Refresh access token
Future<bool> refreshToken() async {
final result = await _repository.refreshToken();
return result.fold(
(failure) {
// If token refresh fails, logout user
logout();
return false;
},
(authResponse) {
state = state.copyWith(user: authResponse.user);
return true;
},
);
}
/// Logout user
Future<void> logout() async {
state = state.copyWith(isLoading: true);
await _repository.logout();
state = const AuthState(
isAuthenticated: false,
isLoading: false,
);
}
}
/// Current authenticated user provider
@riverpod
User? currentUser(Ref ref) {
final authState = ref.watch(authProvider);
return authState.user;
}
/// Is authenticated provider
@riverpod
bool isAuthenticated(Ref ref) {
final authState = ref.watch(authProvider);
return authState.isAuthenticated;
}

View File

@@ -0,0 +1,204 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'auth_provider.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
/// Provider for AuthRepository
@ProviderFor(authRepository)
const authRepositoryProvider = AuthRepositoryProvider._();
/// Provider for AuthRepository
final class AuthRepositoryProvider
extends $FunctionalProvider<AuthRepository, AuthRepository, AuthRepository>
with $Provider<AuthRepository> {
/// Provider for AuthRepository
const AuthRepositoryProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'authRepositoryProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$authRepositoryHash();
@$internal
@override
$ProviderElement<AuthRepository> $createElement($ProviderPointer pointer) =>
$ProviderElement(pointer);
@override
AuthRepository create(Ref ref) {
return authRepository(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(AuthRepository value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<AuthRepository>(value),
);
}
}
String _$authRepositoryHash() => r'0483b13ac95333b56a1a82f6c9fdb64ae46f287d';
/// Auth state notifier provider
@ProviderFor(Auth)
const authProvider = AuthProvider._();
/// Auth state notifier provider
final class AuthProvider extends $NotifierProvider<Auth, AuthState> {
/// Auth state notifier provider
const AuthProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'authProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$authHash();
@$internal
@override
Auth create() => Auth();
/// {@macro riverpod.override_with_value}
Override overrideWithValue(AuthState value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<AuthState>(value),
);
}
}
String _$authHash() => r'c88e150224fa855ed0ddfba30bef9e2b289f329d';
/// Auth state notifier provider
abstract class _$Auth extends $Notifier<AuthState> {
AuthState build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<AuthState, AuthState>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<AuthState, AuthState>,
AuthState,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}
/// Current authenticated user provider
@ProviderFor(currentUser)
const currentUserProvider = CurrentUserProvider._();
/// Current authenticated user provider
final class CurrentUserProvider extends $FunctionalProvider<User?, User?, User?>
with $Provider<User?> {
/// Current authenticated user provider
const CurrentUserProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'currentUserProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$currentUserHash();
@$internal
@override
$ProviderElement<User?> $createElement($ProviderPointer pointer) =>
$ProviderElement(pointer);
@override
User? create(Ref ref) {
return currentUser(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(User? value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<User?>(value),
);
}
}
String _$currentUserHash() => r'4c8cb60cef35a4fd001291434558037d6c85faf5';
/// Is authenticated provider
@ProviderFor(isAuthenticated)
const isAuthenticatedProvider = IsAuthenticatedProvider._();
/// Is authenticated provider
final class IsAuthenticatedProvider
extends $FunctionalProvider<bool, bool, bool>
with $Provider<bool> {
/// Is authenticated provider
const IsAuthenticatedProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'isAuthenticatedProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$isAuthenticatedHash();
@$internal
@override
$ProviderElement<bool> $createElement($ProviderPointer pointer) =>
$ProviderElement(pointer);
@override
bool create(Ref ref) {
return isAuthenticated(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(bool value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<bool>(value),
);
}
}
String _$isAuthenticatedHash() => r'003f7e85bfa5ae774792659ce771b5b59ebf04f8';