2025-11-19 00:36:28 +05:30

152 lines
4.2 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';
// Provide a single ApiService instance across the app
final apiServiceProvider = Provider<ApiService>((ref) => ApiService());
// Provide repository that depends on ApiService
final userRepositoryProvider = Provider<UserRepositoryImpl>(
(ref) => UserRepositoryImpl(ref.read(apiServiceProvider)),
);
// Manage user state
final loginProvider = StateNotifierProvider<UserNotifier, AsyncValue<User?>>((
ref,
) {
final repo = ref.read(userRepositoryProvider);
return UserNotifier(repo);
});
final signupProvider = StateNotifierProvider<UserNotifier, AsyncValue<User?>>((
ref,
) {
final repo = ref.read(userRepositoryProvider);
return UserNotifier(repo);
});
final userProvider = StateNotifierProvider<UserNotifier, AsyncValue<User?>>((
ref,
) {
final repo = ref.read(userRepositoryProvider);
return UserNotifier(repo);
});
final userDetailsProvider = FutureProvider<UserModel?>((ref) async {
final userAsync = ref.watch(userProvider);
// Waiting for login provider to finish
if (userAsync.isLoading) return null;
final user = userAsync.value;
if (user == null) return null;
// Fetch Full Details
final repo = ref.read(userRepositoryProvider);
return await repo.getUserDetails(user.id);
});
enum AuthAction { idle, login, signup }
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 saved user from storage (auto-login)
Future<void> loadUserFromStorage() async {
final jsonString = await _storage.read(key: _userKey);
if (jsonString != null) {
debugPrint("RESULT: $jsonString");
final jsonData = jsonDecode(jsonString);
final user = UserModel.fromJson(jsonData);
await Future.microtask(() {});
state = AsyncValue.data(user);
}
}
///Login
Future<void> login(String email, String password) async {
lastAction = AuthAction.login;
state = const AsyncValue.loading();
try {
final user = await repository.login(email, password);
// ✅ Save user to secure storage
if (user is UserModel) {
await _storage.write(key: _userKey, value: user.toRawJson());
}
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);
}
///Sign up
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 user details from backend
Future<void> getUserDetails(String userId) async {
state = const AsyncValue.loading();
try {
final user = await repository.getUserDetails(userId);
// Save full details separately
await saveUserDetails(user);
state = AsyncValue.data(user);
} catch (e, st) {
state = AsyncValue.error(e, st);
}
}
/// Save full user details separately
Future<void> saveUserDetails(UserModel user) async {
await _storage.write(
key: 'logged_in_user_details',
value: user.toRawJson(),
);
}
}