271 lines
6.8 KiB
Markdown
271 lines
6.8 KiB
Markdown
# Cart API Integration - Quick Start Guide
|
|
|
|
## Files Created
|
|
|
|
### Core Files (Ready to Use)
|
|
1. `/Users/ssg/project/worker/lib/core/constants/api_constants.dart` - Updated with cart endpoints
|
|
2. `/Users/ssg/project/worker/lib/features/cart/domain/repositories/cart_repository.dart` - Repository interface
|
|
3. `/Users/ssg/project/worker/lib/features/cart/data/datasources/cart_remote_datasource.dart` - API calls
|
|
4. `/Users/ssg/project/worker/lib/features/cart/data/datasources/cart_local_datasource.dart` - Hive storage
|
|
5. `/Users/ssg/project/worker/lib/features/cart/data/repositories/cart_repository_impl.dart` - Implementation
|
|
|
|
### Generated Files (Riverpod)
|
|
6. `/Users/ssg/project/worker/lib/features/cart/data/datasources/cart_remote_datasource.g.dart`
|
|
7. `/Users/ssg/project/worker/lib/features/cart/data/datasources/cart_local_datasource.g.dart`
|
|
8. `/Users/ssg/project/worker/lib/features/cart/data/repositories/cart_repository_impl.g.dart`
|
|
|
|
### Documentation
|
|
9. `/Users/ssg/project/worker/lib/features/cart/CART_API_INTEGRATION.md` - Detailed docs
|
|
10. `/Users/ssg/project/worker/CART_API_INTEGRATION_SUMMARY.md` - Complete summary
|
|
11. `/Users/ssg/project/worker/CART_API_QUICK_START.md` - This file
|
|
|
|
## Quick Usage
|
|
|
|
### 1. Import the Repository
|
|
|
|
```dart
|
|
import 'package:worker/features/cart/data/repositories/cart_repository_impl.dart';
|
|
import 'package:worker/features/cart/domain/entities/cart_item.dart';
|
|
```
|
|
|
|
### 2. Use in Your Provider
|
|
|
|
```dart
|
|
@riverpod
|
|
class Cart extends _$Cart {
|
|
CartRepository get _repository => ref.read(cartRepositoryProvider);
|
|
|
|
// Add to cart
|
|
Future<void> addProductToCart(Product product, double quantity) async {
|
|
try {
|
|
final items = await _repository.addToCart(
|
|
itemIds: [product.erpnextItemCode ?? product.productId],
|
|
quantities: [quantity],
|
|
prices: [product.basePrice],
|
|
);
|
|
// Update UI state with items
|
|
} catch (e) {
|
|
// Show error
|
|
}
|
|
}
|
|
|
|
// Get cart items
|
|
Future<void> loadCart() async {
|
|
try {
|
|
final items = await _repository.getCartItems();
|
|
// Update UI state with items
|
|
} catch (e) {
|
|
// Show error
|
|
}
|
|
}
|
|
|
|
// Remove from cart
|
|
Future<void> removeProduct(String itemId) async {
|
|
try {
|
|
await _repository.removeFromCart(itemIds: [itemId]);
|
|
// Update UI state
|
|
} catch (e) {
|
|
// Show error
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## API Methods Available
|
|
|
|
```dart
|
|
// Add items to cart (replaces/updates existing)
|
|
Future<List<CartItem>> addToCart({
|
|
required List<String> itemIds, // ERPNext item codes
|
|
required List<double> quantities,
|
|
required List<double> prices,
|
|
});
|
|
|
|
// Remove items from cart
|
|
Future<bool> removeFromCart({
|
|
required List<String> itemIds,
|
|
});
|
|
|
|
// Get all cart items
|
|
Future<List<CartItem>> getCartItems();
|
|
|
|
// Update quantity (uses addToCart internally)
|
|
Future<List<CartItem>> updateQuantity({
|
|
required String itemId,
|
|
required double quantity,
|
|
required double price,
|
|
});
|
|
|
|
// Clear entire cart
|
|
Future<bool> clearCart();
|
|
|
|
// Get cart total
|
|
Future<double> getCartTotal();
|
|
|
|
// Get cart item count
|
|
Future<int> getCartItemCount();
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
All methods can throw:
|
|
- `NoInternetException` - No network connection
|
|
- `TimeoutException` - Request timeout
|
|
- `UnauthorizedException` - 401 auth error
|
|
- `ForbiddenException` - 403 permission error
|
|
- `NotFoundException` - 404 not found
|
|
- `ServerException` - 5xx server error
|
|
- `NetworkException` - Other network errors
|
|
- `StorageException` - Local storage error
|
|
- `ValidationException` - Invalid input
|
|
- `UnknownException` - Unexpected error
|
|
|
|
## Important Notes
|
|
|
|
### Product ID Mapping
|
|
```dart
|
|
// ALWAYS use erpnextItemCode for API calls
|
|
final itemId = product.erpnextItemCode ?? product.productId;
|
|
|
|
await _repository.addToCart(
|
|
itemIds: [itemId], // ERPNext code, not UUID
|
|
quantities: [quantity],
|
|
prices: [product.basePrice],
|
|
);
|
|
```
|
|
|
|
### Offline Support
|
|
- Read operations fallback to local storage when offline
|
|
- Write operations save locally and queue for sync (TODO)
|
|
- Cart persists across app restarts
|
|
|
|
### Response Format
|
|
Methods return domain `CartItem` entities:
|
|
```dart
|
|
class CartItem {
|
|
final String cartItemId;
|
|
final String cartId;
|
|
final String productId; // ERPNext item code
|
|
final double quantity;
|
|
final double unitPrice;
|
|
final double subtotal;
|
|
final DateTime addedAt;
|
|
}
|
|
```
|
|
|
|
## Common Patterns
|
|
|
|
### Add Product to Cart
|
|
```dart
|
|
void onAddToCart(Product product) async {
|
|
try {
|
|
setState(() => _isLoading = true);
|
|
|
|
await _repository.addToCart(
|
|
itemIds: [product.erpnextItemCode ?? product.productId],
|
|
quantities: [1.0],
|
|
prices: [product.basePrice],
|
|
);
|
|
|
|
// Show success
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('Added to cart')),
|
|
);
|
|
} catch (e) {
|
|
// Show error
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('Failed to add to cart')),
|
|
);
|
|
} finally {
|
|
setState(() => _isLoading = false);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Load Cart on Page Open
|
|
```dart
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadCart();
|
|
}
|
|
|
|
Future<void> _loadCart() async {
|
|
try {
|
|
final items = await ref.read(cartRepositoryProvider).getCartItems();
|
|
// Update state
|
|
} catch (e) {
|
|
// Handle error
|
|
}
|
|
}
|
|
```
|
|
|
|
### Update Quantity
|
|
```dart
|
|
Future<void> onQuantityChanged(String itemId, double newQuantity, double price) async {
|
|
try {
|
|
await _repository.updateQuantity(
|
|
itemId: itemId,
|
|
quantity: newQuantity,
|
|
price: price,
|
|
);
|
|
// Reload cart
|
|
await loadCart();
|
|
} catch (e) {
|
|
// Show error
|
|
}
|
|
}
|
|
```
|
|
|
|
### Remove Item
|
|
```dart
|
|
Future<void> onRemoveItem(String itemId) async {
|
|
try {
|
|
await _repository.removeFromCart(itemIds: [itemId]);
|
|
// Reload cart
|
|
await loadCart();
|
|
} catch (e) {
|
|
// Show error
|
|
}
|
|
}
|
|
```
|
|
|
|
## Testing
|
|
|
|
Run tests with:
|
|
```bash
|
|
flutter test
|
|
```
|
|
|
|
Test files location:
|
|
- `/Users/ssg/project/worker/test/features/cart/`
|
|
|
|
## Troubleshooting
|
|
|
|
### Issue: "Box is already open and of type Box<dynamic>"
|
|
**Solution**: The datasource already uses `Box<dynamic>`. Don't re-open boxes with specific types.
|
|
|
|
### Issue: "Network error" on every request
|
|
**Solution**: Check if user is authenticated. Cart endpoints require valid session.
|
|
|
|
### Issue: Items not syncing to API
|
|
**Solution**: Check network connection. Items save locally when offline.
|
|
|
|
### Issue: "ProductId not found in cart"
|
|
**Solution**: Use ERPNext item code, not product UUID. Check `product.erpnextItemCode`.
|
|
|
|
## Next Steps
|
|
|
|
1. Update existing `cart_provider.dart` to use repository
|
|
2. Add loading states to cart UI
|
|
3. Add error messages with SnackBar
|
|
4. Test all cart operations
|
|
5. Implement offline queue (optional)
|
|
|
|
## Support
|
|
|
|
For questions or issues:
|
|
- Check `/Users/ssg/project/worker/lib/features/cart/CART_API_INTEGRATION.md` for detailed docs
|
|
- Check `/Users/ssg/project/worker/CART_API_INTEGRATION_SUMMARY.md` for architecture overview
|
|
- Review code comments in source files
|