187 lines
5.6 KiB
Dart
187 lines
5.6 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:autos/data/models/user_model.dart';
|
|
import 'package:autos/data/repositories/user_repository_impl.dart';
|
|
import 'package:autos/data/sources/remote/api_service.dart';
|
|
import 'package:autos/domain/entities/user.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:flutter_riverpod/legacy.dart';
|
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
|
|
/// ------------------------------------------------------------
|
|
/// API SERVICE
|
|
/// ------------------------------------------------------------
|
|
final apiServiceProvider = Provider<ApiService>((ref) => ApiService());
|
|
|
|
/// ------------------------------------------------------------
|
|
/// USER REPOSITORY
|
|
/// ------------------------------------------------------------
|
|
final userRepositoryProvider = Provider<UserRepositoryImpl>(
|
|
(ref) => UserRepositoryImpl(ref.read(apiServiceProvider)),
|
|
);
|
|
|
|
/// ------------------------------------------------------------
|
|
/// LOGIN PROVIDER ✅ (UNCHANGED NAME)
|
|
/// ------------------------------------------------------------
|
|
final loginProvider =
|
|
StateNotifierProvider<UserNotifier, AsyncValue<User?>>((ref) {
|
|
final repo = ref.read(userRepositoryProvider);
|
|
return UserNotifier(repo);
|
|
});
|
|
|
|
/// ------------------------------------------------------------
|
|
/// SIGNUP PROVIDER ✅ (UNCHANGED NAME)
|
|
/// ------------------------------------------------------------
|
|
final signupProvider =
|
|
StateNotifierProvider<UserNotifier, AsyncValue<User?>>((ref) {
|
|
final repo = ref.read(userRepositoryProvider);
|
|
return UserNotifier(repo);
|
|
});
|
|
|
|
/// ------------------------------------------------------------
|
|
/// MAIN USER PROVIDER ✅ (UNCHANGED NAME)
|
|
/// AUTO LOADS FROM STORAGE
|
|
/// ------------------------------------------------------------
|
|
final userProvider =
|
|
StateNotifierProvider<UserNotifier, AsyncValue<User?>>((ref) {
|
|
final repo = ref.read(userRepositoryProvider);
|
|
final notifier = UserNotifier(repo);
|
|
|
|
/// ✅ AUTO RESTORE SESSION ON APP START
|
|
notifier.loadUserFromStorage();
|
|
|
|
return notifier;
|
|
});
|
|
|
|
/// ------------------------------------------------------------
|
|
/// USER DETAILS PROVIDER ✅ (UNCHANGED NAME)
|
|
/// ------------------------------------------------------------
|
|
final userDetailsProvider = FutureProvider<UserModel?>((ref) async {
|
|
final userAsync = ref.watch(userProvider);
|
|
|
|
if (userAsync.isLoading) return null;
|
|
|
|
final user = userAsync.value;
|
|
if (user == null) return null;
|
|
|
|
final repo = ref.read(userRepositoryProvider);
|
|
return await repo.getUserDetails(user.id);
|
|
});
|
|
|
|
/// ------------------------------------------------------------
|
|
/// AUTH STATE
|
|
/// ------------------------------------------------------------
|
|
enum AuthAction { idle, login, signup }
|
|
|
|
/// ------------------------------------------------------------
|
|
/// USER NOTIFIER ✅
|
|
/// ------------------------------------------------------------
|
|
class UserNotifier extends StateNotifier<AsyncValue<User?>> {
|
|
final UserRepositoryImpl repository;
|
|
final _storage = const FlutterSecureStorage();
|
|
static const _userKey = 'logged_in_user';
|
|
|
|
AuthAction lastAction = AuthAction.idle;
|
|
|
|
UserNotifier(this.repository) : super(const AsyncValue.data(null));
|
|
|
|
/// ✅ LOAD USER FROM STORAGE (FIXED)
|
|
Future<void> loadUserFromStorage() async {
|
|
try {
|
|
final jsonString = await _storage.read(key: _userKey);
|
|
|
|
if (jsonString == null) {
|
|
debugPrint("🟡 No user found in storage");
|
|
return;
|
|
}
|
|
|
|
final jsonData = jsonDecode(jsonString);
|
|
final user = UserModel.fromJson(jsonData);
|
|
|
|
state = AsyncValue.data(user);
|
|
|
|
debugPrint("✅ USER RESTORED → ID: ${user.id}");
|
|
} catch (e) {
|
|
debugPrint("❌ Storage restore failed: $e");
|
|
state = const AsyncValue.data(null);
|
|
}
|
|
}
|
|
|
|
/// ✅ LOGIN
|
|
Future<void> login(String email, String password) async {
|
|
lastAction = AuthAction.login;
|
|
state = const AsyncValue.loading();
|
|
|
|
try {
|
|
final user = await repository.login(email, password);
|
|
|
|
if (user is UserModel) {
|
|
await _storage.write(key: _userKey, value: user.toRawJson());
|
|
debugPrint("✅ USER SAVED → ID: ${user.id}");
|
|
}
|
|
|
|
state = AsyncValue.data(user);
|
|
} catch (e, st) {
|
|
state = AsyncValue.error(e, st);
|
|
}
|
|
}
|
|
|
|
/// ✅ LOGOUT
|
|
Future<void> logout() async {
|
|
await _storage.delete(key: _userKey);
|
|
state = const AsyncValue.data(null);
|
|
}
|
|
|
|
/// ✅ SIGNUP
|
|
Future<void> signup(
|
|
String name,
|
|
String email,
|
|
String password,
|
|
String phone,
|
|
) async {
|
|
lastAction = AuthAction.signup;
|
|
state = const AsyncValue.loading();
|
|
|
|
try {
|
|
final user = await repository.signup(name, email, password, phone);
|
|
state = AsyncValue.data(user);
|
|
} catch (e, st) {
|
|
state = AsyncValue.error(e, st);
|
|
}
|
|
}
|
|
|
|
/// ✅ RESET PASSWORD
|
|
Future<void> sendPasswordResetLink(String email) async {
|
|
state = const AsyncValue.loading();
|
|
|
|
try {
|
|
await repository.sendPasswordResetLink(email);
|
|
state = const AsyncValue.data(null);
|
|
} catch (e, st) {
|
|
state = AsyncValue.error(e, st);
|
|
}
|
|
}
|
|
|
|
/// ✅ FETCH FULL USER DETAILS
|
|
Future<void> getUserDetails(String userId) async {
|
|
state = const AsyncValue.loading();
|
|
|
|
try {
|
|
final user = await repository.getUserDetails(userId);
|
|
await saveUserDetails(user);
|
|
state = AsyncValue.data(user);
|
|
} catch (e, st) {
|
|
state = AsyncValue.error(e, st);
|
|
}
|
|
}
|
|
|
|
/// ✅ SAVE FULL DETAILS
|
|
Future<void> saveUserDetails(UserModel user) async {
|
|
await _storage.write(
|
|
key: 'logged_in_user_details',
|
|
value: user.toRawJson(),
|
|
);
|
|
}
|
|
}
|