runable
This commit is contained in:
345
docs/API_QUICK_REFERENCE.md
Normal file
345
docs/API_QUICK_REFERENCE.md
Normal file
@@ -0,0 +1,345 @@
|
||||
# API Integration - Quick Reference Card
|
||||
|
||||
## Essential Files
|
||||
|
||||
| File | Purpose | Key Methods |
|
||||
|------|---------|-------------|
|
||||
| `api_constants.dart` | API config | `baseUrl`, endpoints, timeouts |
|
||||
| `dio_client.dart` | HTTP client | `get()`, `post()`, `put()`, `delete()` |
|
||||
| `network_info.dart` | Connectivity | `isConnected`, `onConnectivityChanged` |
|
||||
| `exceptions.dart` | Error types | 20+ exception classes |
|
||||
| `failures.dart` | Domain errors | Failure classes for UI |
|
||||
| `product_remote_datasource.dart` | Product API | `fetchProducts()`, `searchProducts()` |
|
||||
| `category_remote_datasource.dart` | Category API | `fetchCategories()` |
|
||||
|
||||
## Quick Setup (5 Steps)
|
||||
|
||||
```dart
|
||||
// 1. In main.dart - Initialize dependencies
|
||||
import 'core/di/injection_container.dart' as di;
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await di.initDependencies();
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
// 2. Configure API URL in api_constants.dart
|
||||
static const String baseUrl = 'https://your-api.com';
|
||||
|
||||
// 3. Enable mock data for testing (optional)
|
||||
static const bool useMockData = true;
|
||||
|
||||
// 4. Get data source from service locator
|
||||
final productDS = sl<ProductRemoteDataSource>();
|
||||
|
||||
// 5. Fetch data
|
||||
final products = await productDS.fetchProducts();
|
||||
```
|
||||
|
||||
## Common Operations
|
||||
|
||||
### Fetch All Products
|
||||
```dart
|
||||
final dataSource = sl<ProductRemoteDataSource>();
|
||||
final products = await dataSource.fetchProducts();
|
||||
```
|
||||
|
||||
### Search Products
|
||||
```dart
|
||||
final results = await dataSource.searchProducts('laptop');
|
||||
```
|
||||
|
||||
### Fetch by Category
|
||||
```dart
|
||||
final products = await dataSource.fetchProductsByCategory('electronics');
|
||||
```
|
||||
|
||||
### Fetch Single Product
|
||||
```dart
|
||||
final product = await dataSource.fetchProductById('123');
|
||||
```
|
||||
|
||||
### Fetch Categories
|
||||
```dart
|
||||
final categoryDS = sl<CategoryRemoteDataSource>();
|
||||
final categories = await categoryDS.fetchCategories();
|
||||
```
|
||||
|
||||
### Check Connectivity
|
||||
```dart
|
||||
final networkInfo = sl<NetworkInfo>();
|
||||
final isConnected = await networkInfo.isConnected;
|
||||
```
|
||||
|
||||
## Error Handling Patterns
|
||||
|
||||
### Basic Try-Catch
|
||||
```dart
|
||||
try {
|
||||
final products = await dataSource.fetchProducts();
|
||||
// Use products
|
||||
} on NoInternetException {
|
||||
// Show "No internet" message
|
||||
} on ServerException catch (e) {
|
||||
// Show "Server error: ${e.message}"
|
||||
} on NetworkException catch (e) {
|
||||
// Show "Network error: ${e.message}"
|
||||
}
|
||||
```
|
||||
|
||||
### With Network Check
|
||||
```dart
|
||||
final networkInfo = sl<NetworkInfo>();
|
||||
if (!await networkInfo.isConnected) {
|
||||
// Load from cache or show offline UI
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final products = await dataSource.fetchProducts();
|
||||
// Use products
|
||||
} catch (e) {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Repository Pattern (Recommended)
|
||||
```dart
|
||||
Future<Either<Failure, List<Product>>> getProducts() async {
|
||||
if (!await networkInfo.isConnected) {
|
||||
return Left(NoInternetFailure());
|
||||
}
|
||||
|
||||
try {
|
||||
final products = await remoteDataSource.fetchProducts();
|
||||
return Right(products);
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message, e.statusCode));
|
||||
} on NetworkException catch (e) {
|
||||
return Left(NetworkFailure(e.message));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Exception → Failure Mapping
|
||||
|
||||
| Exception | Failure | UI Message |
|
||||
|-----------|---------|------------|
|
||||
| `NoInternetException` | `NoInternetFailure` | "No internet connection" |
|
||||
| `TimeoutException` | `TimeoutFailure` | "Request timeout" |
|
||||
| `ServerException (500+)` | `ServerFailure` | "Server error" |
|
||||
| `UnauthorizedException (401)` | `UnauthorizedFailure` | "Please login" |
|
||||
| `NotFoundException (404)` | `NotFoundFailure` | "Not found" |
|
||||
| `ValidationException (422)` | `ValidationFailure` | "Invalid data" |
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### API Constants
|
||||
```dart
|
||||
// In api_constants.dart
|
||||
|
||||
// Base URL
|
||||
static const String baseUrl = 'https://api.example.com';
|
||||
|
||||
// Timeouts (milliseconds)
|
||||
static const int connectTimeout = 30000;
|
||||
static const int receiveTimeout = 30000;
|
||||
|
||||
// Retry
|
||||
static const int maxRetries = 3;
|
||||
static const int retryDelay = 1000;
|
||||
|
||||
// Mock data toggle
|
||||
static const bool useMockData = false;
|
||||
```
|
||||
|
||||
### DioClient Headers
|
||||
```dart
|
||||
final dioClient = DioClient();
|
||||
|
||||
// Add auth token
|
||||
dioClient.updateAuthToken('your-jwt-token');
|
||||
|
||||
// Add custom header
|
||||
dioClient.addHeader('X-Custom', 'value');
|
||||
|
||||
// Remove auth token
|
||||
dioClient.removeAuthToken();
|
||||
```
|
||||
|
||||
## Riverpod Integration
|
||||
|
||||
### Provider Setup
|
||||
```dart
|
||||
@riverpod
|
||||
class Products extends _$Products {
|
||||
@override
|
||||
Future<List<ProductModel>> build() async {
|
||||
final dataSource = sl<ProductRemoteDataSource>();
|
||||
return await dataSource.fetchProducts();
|
||||
}
|
||||
|
||||
Future<void> refresh() async {
|
||||
state = const AsyncValue.loading();
|
||||
state = await AsyncValue.guard(() async {
|
||||
final dataSource = sl<ProductRemoteDataSource>();
|
||||
return await dataSource.fetchProducts();
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### UI Usage
|
||||
```dart
|
||||
Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final productsAsync = ref.watch(productsProvider);
|
||||
|
||||
return productsAsync.when(
|
||||
data: (products) => ProductList(products),
|
||||
loading: () => CircularProgressIndicator(),
|
||||
error: (error, stack) => ErrorWidget(error),
|
||||
);
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
## API Endpoints Reference
|
||||
|
||||
### Products
|
||||
| Method | Endpoint | Purpose |
|
||||
|--------|----------|---------|
|
||||
| GET | `/products` | Get all products |
|
||||
| GET | `/products/:id` | Get single product |
|
||||
| GET | `/products/category/:id` | Get by category |
|
||||
| GET | `/products/search?q=query` | Search products |
|
||||
| POST | `/products/sync` | Bulk sync |
|
||||
|
||||
### Categories
|
||||
| Method | Endpoint | Purpose |
|
||||
|--------|----------|---------|
|
||||
| GET | `/categories` | Get all categories |
|
||||
| GET | `/categories/:id` | Get single category |
|
||||
| POST | `/categories/sync` | Bulk sync |
|
||||
|
||||
## Expected Response Formats
|
||||
|
||||
### Products List
|
||||
```json
|
||||
{
|
||||
"products": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Product Name",
|
||||
"price": 29.99,
|
||||
"categoryId": "cat1",
|
||||
"stockQuantity": 100,
|
||||
"isAvailable": true,
|
||||
"createdAt": "2024-01-01T00:00:00Z",
|
||||
"updatedAt": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Categories List
|
||||
```json
|
||||
{
|
||||
"categories": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Electronics",
|
||||
"productCount": 25,
|
||||
"createdAt": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Error Response
|
||||
```json
|
||||
{
|
||||
"message": "Error message",
|
||||
"error": "Detailed error"
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Quick Start
|
||||
|
||||
### Use Mock Data Source
|
||||
```dart
|
||||
// In api_constants.dart
|
||||
static const bool useMockData = true;
|
||||
|
||||
// Or directly
|
||||
final mockDS = ProductRemoteDataSourceMock();
|
||||
final products = await mockDS.fetchProducts();
|
||||
```
|
||||
|
||||
### Mock Network Status
|
||||
```dart
|
||||
final mockNetwork = NetworkInfoMock(isConnected: false);
|
||||
final isConnected = await mockNetwork.isConnected; // false
|
||||
```
|
||||
|
||||
## Common Issues & Solutions
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| Connection timeout | Increase timeout in `api_constants.dart` |
|
||||
| SSL certificate error | Configure `badCertificateCallback` (dev only) |
|
||||
| 401 Unauthorized | Update auth token with `updateAuthToken()` |
|
||||
| Mock data not working | Check `useMockData = true` |
|
||||
| Parsing error | Verify response format matches model |
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. **Enable caching**: Use Hive to cache API responses
|
||||
2. **Pagination**: Request data in chunks (20-50 items)
|
||||
3. **Debounce search**: Wait 300ms before searching
|
||||
4. **Image optimization**: Use `cached_network_image`
|
||||
5. **Background sync**: Sync during app idle time
|
||||
6. **Cancel requests**: Use `CancelToken` for expensive operations
|
||||
|
||||
## Debug Logging
|
||||
|
||||
Logs are automatically generated:
|
||||
```
|
||||
REQUEST[GET] => PATH: /products
|
||||
Headers: {Content-Type: application/json}
|
||||
RESPONSE[200] => PATH: /products
|
||||
Data: {...}
|
||||
```
|
||||
|
||||
Disable in production by removing `LoggingInterceptor`.
|
||||
|
||||
## Security Checklist
|
||||
|
||||
- [ ] Use HTTPS (not HTTP)
|
||||
- [ ] Store API keys securely (use `flutter_secure_storage`)
|
||||
- [ ] Implement token refresh for expired tokens
|
||||
- [ ] Validate SSL certificates in production
|
||||
- [ ] Don't log sensitive data in production
|
||||
- [ ] Use environment variables for API URLs
|
||||
- [ ] Implement rate limiting on client side
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. ✅ API integration complete
|
||||
2. → Create Repository layer
|
||||
3. → Implement Use Cases
|
||||
4. → Wire up Riverpod Providers
|
||||
5. → Build UI with error handling
|
||||
6. → Add offline sync
|
||||
7. → Implement authentication
|
||||
8. → Add unit tests
|
||||
|
||||
---
|
||||
|
||||
**Quick Links:**
|
||||
- Full Guide: `API_INTEGRATION_GUIDE.md`
|
||||
- Architecture: `API_ARCHITECTURE.md`
|
||||
- Examples: `examples/api_usage_example.dart`
|
||||
|
||||
**Status**: ✅ Ready to Use
|
||||
Reference in New Issue
Block a user