update info

This commit is contained in:
Phuoc Nguyen
2025-11-20 10:12:24 +07:00
parent 54cb7d0fdd
commit 0708ed7d6f
17 changed files with 2144 additions and 161 deletions

View File

@@ -0,0 +1,131 @@
/// User Info Remote Data Source
///
/// Handles API calls for fetching user information.
library;
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:worker/core/errors/exceptions.dart';
import 'package:worker/core/network/dio_client.dart';
import 'package:worker/features/account/data/models/user_info_model.dart';
/// User Info Remote Data Source
///
/// Provides methods for:
/// - Fetching current user information from API
/// - Uses existing Frappe authentication (cookies/tokens)
class UserInfoRemoteDataSource {
UserInfoRemoteDataSource(this._dioClient);
final DioClient _dioClient;
/// Get User Info
///
/// Fetches the current authenticated user's information.
/// Uses existing Frappe session cookies/tokens for authentication.
///
/// API: POST https://land.dbiz.com/api/method/building_material.building_material.api.user.get_user_info
/// Request: Empty POST (no body required)
///
/// Response structure:
/// ```json
/// {
/// "message": {
/// "user_id": "...",
/// "full_name": "...",
/// "email": "...",
/// "phone_number": "...",
/// "role": "customer",
/// "status": "active",
/// "loyalty_tier": "gold",
/// "total_points": 1000,
/// "available_points": 800,
/// "expiring_points": 200,
/// // ... other fields
/// }
/// }
/// ```
///
/// Throws:
/// - [UnauthorizedException] if user not authenticated (401)
/// - [NotFoundException] if endpoint not found (404)
/// - [ServerException] if server error occurs (500+)
/// - [NetworkException] for other network errors
Future<UserInfoModel> getUserInfo() async {
try {
debugPrint('🔵 [UserInfoDataSource] Fetching user info...');
final startTime = DateTime.now();
// Make POST request with empty body
// Authentication is handled by auth interceptor (uses existing session)
final response = await _dioClient.post<Map<String, dynamic>>(
'/api/method/building_material.building_material.api.user.get_user_info',
data: const <String, dynamic>{}, // Empty body as per API spec
);
final duration = DateTime.now().difference(startTime);
debugPrint('🟢 [UserInfoDataSource] Response received in ${duration.inMilliseconds}ms');
debugPrint('🟢 [UserInfoDataSource] Status: ${response.statusCode}');
debugPrint('🟢 [UserInfoDataSource] Data: ${response.data}');
// Check response status and data
if (response.statusCode == 200 && response.data != null) {
// Parse response to model
final model = UserInfoModel.fromJson(response.data!);
debugPrint('✅ [UserInfoDataSource] Successfully parsed user: ${model.fullName}');
return model;
} else {
throw ServerException(
'Failed to get user info: ${response.statusCode}',
response.statusCode,
);
}
} on DioException catch (e) {
// Handle specific HTTP status codes
if (e.response?.statusCode == 401) {
throw const UnauthorizedException(
'Session expired. Please login again.',
);
} else if (e.response?.statusCode == 403) {
throw const ForbiddenException();
} else if (e.response?.statusCode == 404) {
throw NotFoundException('User info endpoint not found');
} else if (e.response?.statusCode != null &&
e.response!.statusCode! >= 500) {
throw ServerException(
'Server error: ${e.response?.statusMessage ?? "Unknown error"}',
e.response?.statusCode,
);
} else if (e.type == DioExceptionType.connectionTimeout ||
e.type == DioExceptionType.receiveTimeout) {
throw const TimeoutException();
} else if (e.type == DioExceptionType.connectionError) {
throw const NoInternetException();
} else {
throw NetworkException(
e.message ?? 'Failed to get user info',
statusCode: e.response?.statusCode,
);
}
} catch (e) {
// Handle unexpected errors
if (e is ServerException ||
e is UnauthorizedException ||
e is NetworkException ||
e is NotFoundException) {
rethrow;
}
throw ServerException('Unexpected error: $e');
}
}
/// Refresh User Info
///
/// Same as getUserInfo but with force refresh parameter.
/// Useful when you want to bypass cache and get fresh data.
Future<UserInfoModel> refreshUserInfo() async {
// For now, same as getUserInfo
// Could add cache-busting headers in the future if needed
return getUserInfo();
}
}