Files
worker/docs/CART_API_QUICK_START.md
Phuoc Nguyen 192c322816 a
2025-11-17 17:56:34 +07:00

6.8 KiB

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)

  1. /Users/ssg/project/worker/lib/features/cart/data/datasources/cart_remote_datasource.g.dart
  2. /Users/ssg/project/worker/lib/features/cart/data/datasources/cart_local_datasource.g.dart
  3. /Users/ssg/project/worker/lib/features/cart/data/repositories/cart_repository_impl.g.dart

Documentation

  1. /Users/ssg/project/worker/lib/features/cart/CART_API_INTEGRATION.md - Detailed docs
  2. /Users/ssg/project/worker/CART_API_INTEGRATION_SUMMARY.md - Complete summary
  3. /Users/ssg/project/worker/CART_API_QUICK_START.md - This file

Quick Usage

1. Import the Repository

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

@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

// 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

// 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:

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

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

@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

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

Future<void> onRemoveItem(String itemId) async {
  try {
    await _repository.removeFromCart(itemIds: [itemId]);
    // Reload cart
    await loadCart();
  } catch (e) {
    // Show error
  }
}

Testing

Run tests with:

flutter test

Test files location:

  • /Users/ssg/project/worker/test/features/cart/

Troubleshooting

Issue: "Box is already open and of type Box"

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