# API Client Quick Reference ## Import ```dart import 'package:minhthu/core/core.dart'; ``` ## Initialization ```dart final secureStorage = SecureStorage(); final apiClient = ApiClient( secureStorage, onUnauthorized: () => context.go('/login'), ); ``` ## HTTP Methods ### GET Request ```dart final response = await apiClient.get( '/warehouses', queryParameters: {'limit': 10}, ); ``` ### POST Request ```dart final response = await apiClient.post( '/auth/login', data: {'username': 'user', 'password': 'pass'}, ); ``` ### PUT Request ```dart final response = await apiClient.put( '/products/123', data: {'name': 'Updated'}, ); ``` ### DELETE Request ```dart final response = await apiClient.delete('/products/123'); ``` ## Parse API Response ```dart final apiResponse = ApiResponse.fromJson( response.data, (json) => User.fromJson(json), // or your model ); if (apiResponse.isSuccess && apiResponse.value != null) { final data = apiResponse.value; // Use data } else { final error = apiResponse.getErrorMessage(); // Handle error } ``` ## Error Handling ```dart try { final response = await apiClient.get('/products'); } on NetworkException catch (e) { // Timeout, no internet print('Network error: ${e.message}'); } on ServerException catch (e) { // HTTP errors (401, 404, 500, etc.) print('Server error: ${e.message}'); print('Error code: ${e.code}'); } ``` ## Token Management ### Save Token ```dart await secureStorage.saveAccessToken('your_token'); await secureStorage.saveRefreshToken('refresh_token'); ``` ### Get Token ```dart final token = await secureStorage.getAccessToken(); ``` ### Check Authentication ```dart final isAuthenticated = await apiClient.isAuthenticated(); ``` ### Clear Tokens (Logout) ```dart await apiClient.clearAuth(); ``` ## API Endpoints Use constants from `ApiEndpoints`: ```dart // Authentication ApiEndpoints.login // /auth/login ApiEndpoints.logout // /auth/logout // Warehouses ApiEndpoints.warehouses // /warehouses ApiEndpoints.warehouseById(1) // /warehouses/1 // Products ApiEndpoints.products // /products ApiEndpoints.productById(123) // /products/123 // Query parameters helper ApiEndpoints.productQueryParams( warehouseId: 1, type: 'import', ) // {warehouseId: 1, type: 'import'} ``` ## Utilities ### Test Connection ```dart final isConnected = await apiClient.testConnection(); ``` ### Update Base URL ```dart apiClient.updateBaseUrl('https://dev-api.example.com'); ``` ### Get Current Token ```dart final token = await apiClient.getAccessToken(); ``` ## Common Patterns ### Login Flow ```dart // 1. Login final response = await apiClient.post( ApiEndpoints.login, data: {'username': username, 'password': password}, ); // 2. Parse final apiResponse = ApiResponse.fromJson( response.data, (json) => User.fromJson(json), ); // 3. Save tokens if (apiResponse.isSuccess && apiResponse.value != null) { final user = apiResponse.value!; await secureStorage.saveAccessToken(user.accessToken); await secureStorage.saveUserId(user.userId); } ``` ### Repository Pattern ```dart class WarehouseRemoteDataSourceImpl implements WarehouseRemoteDataSource { final ApiClient apiClient; WarehouseRemoteDataSourceImpl(this.apiClient); @override Future> getWarehouses() async { final response = await apiClient.get(ApiEndpoints.warehouses); final apiResponse = ApiResponse.fromJson( response.data, (json) => (json as List).map((e) => Warehouse.fromJson(e)).toList(), ); if (apiResponse.isSuccess && apiResponse.value != null) { return apiResponse.value!; } else { throw ServerException(apiResponse.getErrorMessage()); } } } ``` ## Configuration ### Set Base URL In `lib/core/constants/app_constants.dart`: ```dart static const String apiBaseUrl = 'https://api.example.com'; ``` ### Set Timeouts In `lib/core/constants/app_constants.dart`: ```dart static const int connectionTimeout = 30000; // 30 seconds static const int receiveTimeout = 30000; static const int sendTimeout = 30000; ``` ## Files Location - API Client: `/lib/core/network/api_client.dart` - API Response: `/lib/core/network/api_response.dart` - Secure Storage: `/lib/core/storage/secure_storage.dart` - API Endpoints: `/lib/core/constants/api_endpoints.dart` - Examples: `/lib/core/network/api_client_example.dart` - Documentation: `/lib/core/network/README.md` ## Important Notes 1. **Automatic Token Injection**: Bearer token is automatically added to all requests 2. **401 Handling**: 401 errors automatically clear tokens and trigger `onUnauthorized` callback 3. **Logging**: All requests/responses are logged with sensitive data redacted 4. **Singleton Storage**: SecureStorage is a singleton - use `SecureStorage()` everywhere 5. **Error Codes**: ServerException includes error codes (e.g., '401', '404', '500') ## Common Issues ### Token not injected? Check if token exists: `await secureStorage.getAccessToken()` ### 401 not clearing tokens? Verify `onUnauthorized` callback is set in ApiClient constructor ### Connection timeout? Check network, verify base URL, increase timeout in constants ### Logs not showing? Check Flutter DevTools console or developer.log output