fix settings

This commit is contained in:
2025-09-26 20:54:32 +07:00
parent 30ed6b39b5
commit 74d0e3d44c
36 changed files with 5040 additions and 192 deletions

View File

@@ -0,0 +1,73 @@
import 'dart:convert';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import '../../../../core/errors/exceptions.dart';
import '../models/user_model.dart';
abstract class AuthLocalDataSource {
Future<void> cacheUser(UserModel user);
Future<UserModel?> getCachedUser();
Future<void> clearCache();
Future<void> cacheToken(String token);
Future<String?> getCachedToken();
}
class AuthLocalDataSourceImpl implements AuthLocalDataSource {
final FlutterSecureStorage secureStorage;
static const String userKey = 'CACHED_USER';
static const String tokenKey = 'AUTH_TOKEN';
AuthLocalDataSourceImpl({required this.secureStorage});
@override
Future<void> cacheUser(UserModel user) async {
try {
final userJson = json.encode(user.toJson());
await secureStorage.write(key: userKey, value: userJson);
} catch (e) {
throw CacheException('Failed to cache user');
}
}
@override
Future<UserModel?> getCachedUser() async {
try {
final userJson = await secureStorage.read(key: userKey);
if (userJson != null) {
final userMap = json.decode(userJson) as Map<String, dynamic>;
return UserModel.fromJson(userMap);
}
return null;
} catch (e) {
throw CacheException('Failed to get cached user');
}
}
@override
Future<void> clearCache() async {
try {
await secureStorage.delete(key: userKey);
await secureStorage.delete(key: tokenKey);
} catch (e) {
throw CacheException('Failed to clear cache');
}
}
@override
Future<void> cacheToken(String token) async {
try {
await secureStorage.write(key: tokenKey, value: token);
} catch (e) {
throw CacheException('Failed to cache token');
}
}
@override
Future<String?> getCachedToken() async {
try {
return await secureStorage.read(key: tokenKey);
} catch (e) {
throw CacheException('Failed to get cached token');
}
}
}

View File

@@ -0,0 +1,232 @@
import 'package:dio/dio.dart';
import '../../../../core/errors/exceptions.dart';
import '../../../../core/network/dio_client.dart';
import '../models/user_model.dart';
abstract class AuthRemoteDataSource {
Future<UserModel> login({
required String email,
required String password,
});
Future<UserModel> register({
required String email,
required String password,
required String name,
});
Future<void> logout();
Future<UserModel> refreshToken(String token);
Future<UserModel> updateProfile({
required String name,
String? avatarUrl,
});
Future<void> changePassword({
required String oldPassword,
required String newPassword,
});
Future<void> resetPassword({
required String email,
});
}
class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
final DioClient dioClient;
AuthRemoteDataSourceImpl({required this.dioClient});
@override
Future<UserModel> login({
required String email,
required String password,
}) async {
try {
// Using JSONPlaceholder as a mock API
// In real app, this would be your actual auth endpoint
final response = await dioClient.dio.post(
'https://jsonplaceholder.typicode.com/posts',
data: {
'email': email,
'password': password,
},
);
// Mock validation - accept any email/password for demo
// In real app, the server would validate credentials
if (email.isEmpty || password.isEmpty) {
throw const ServerException('Invalid credentials');
}
// Mock response for demonstration
// In real app, parse actual API response
final mockUser = {
'id': '1',
'email': email,
'name': email.split('@').first,
'token': 'mock_jwt_token_${DateTime.now().millisecondsSinceEpoch}',
'tokenExpiry': DateTime.now().add(const Duration(days: 7)).toIso8601String(),
};
return UserModel.fromJson(mockUser);
} on DioException catch (e) {
if (e.response?.statusCode == 401) {
throw const ServerException('Invalid credentials');
} else if (e.response?.statusCode == 404) {
throw const ServerException('User not found');
} else {
throw ServerException(e.message ?? 'Login failed');
}
} catch (e) {
if (e.toString().contains('Invalid credentials')) {
rethrow;
}
throw ServerException(e.toString());
}
}
@override
Future<UserModel> register({
required String email,
required String password,
required String name,
}) async {
try {
// Mock API call
final response = await dioClient.dio.post(
'https://jsonplaceholder.typicode.com/users',
data: {
'email': email,
'password': password,
'name': name,
},
);
// Mock response
final mockUser = {
'id': DateTime.now().millisecondsSinceEpoch.toString(),
'email': email,
'name': name,
'token': 'mock_jwt_token_${DateTime.now().millisecondsSinceEpoch}',
'tokenExpiry': DateTime.now().add(const Duration(days: 7)).toIso8601String(),
};
return UserModel.fromJson(mockUser);
} on DioException catch (e) {
if (e.response?.statusCode == 409) {
throw const ServerException('Email already exists');
} else {
throw ServerException(e.message ?? 'Registration failed');
}
} catch (e) {
throw ServerException(e.toString());
}
}
@override
Future<void> logout() async {
try {
// Mock API call
await dioClient.dio.post('https://jsonplaceholder.typicode.com/posts');
// In real app, you might call a logout endpoint to invalidate token
} catch (e) {
throw ServerException(e.toString());
}
}
@override
Future<UserModel> refreshToken(String token) async {
try {
// Mock API call
final response = await dioClient.dio.post(
'https://jsonplaceholder.typicode.com/users',
options: Options(
headers: {'Authorization': 'Bearer $token'},
),
);
// Mock response
final mockUser = {
'id': '1',
'email': 'user@example.com',
'name': 'User',
'token': 'refreshed_token_${DateTime.now().millisecondsSinceEpoch}',
'tokenExpiry': DateTime.now().add(const Duration(days: 7)).toIso8601String(),
};
return UserModel.fromJson(mockUser);
} catch (e) {
throw ServerException(e.toString());
}
}
@override
Future<UserModel> updateProfile({
required String name,
String? avatarUrl,
}) async {
try {
// Mock API call
final response = await dioClient.dio.put(
'https://jsonplaceholder.typicode.com/users/1',
data: {
'name': name,
'avatarUrl': avatarUrl,
},
);
// Mock response
final mockUser = {
'id': '1',
'email': 'user@example.com',
'name': name,
'avatarUrl': avatarUrl,
'token': 'mock_jwt_token_${DateTime.now().millisecondsSinceEpoch}',
'tokenExpiry': DateTime.now().add(const Duration(days: 7)).toIso8601String(),
};
return UserModel.fromJson(mockUser);
} catch (e) {
throw ServerException(e.toString());
}
}
@override
Future<void> changePassword({
required String oldPassword,
required String newPassword,
}) async {
try {
// Mock API call
await dioClient.dio.post(
'https://jsonplaceholder.typicode.com/posts',
data: {
'oldPassword': oldPassword,
'newPassword': newPassword,
},
);
} catch (e) {
throw ServerException(e.toString());
}
}
@override
Future<void> resetPassword({
required String email,
}) async {
try {
// Mock API call
await dioClient.dio.post(
'https://jsonplaceholder.typicode.com/posts',
data: {
'email': email,
},
);
} catch (e) {
throw ServerException(e.toString());
}
}
}