Add or update cartline(s)

Cart Action

Header

  • Composable Action: composables/useCart/useCartApi.ts
  • API Route: PUT /api/carts/[cartId]/cartlines/add

Detailed Description

The addOrUpdateCartLines action is an essential feature of the cart system that allows adding or updating products in the cart. It plays a central role in cart management by enabling users to:

  • Add new products to the cart
  • Update quantities of existing products
  • Handle bulk modifications

This action is used in several contexts:

  • Cart user interface
  • Quick order process
  • Synchronization between different carts
  • Automatic stock updates

Process Flow

sequenceDiagram
    participant U as User
    participant C as Vue Component
    participant UC as useCart
    participant S as Pinia Store
    participant A as API
    participant Auth as Auth Service

    U->>C: Add/Modify product
    C->>UC: addOrUpdateCartLine(params)
    UC->>Auth: Check authentication
    Auth-->>UC: OK
    UC->>A: PUT /api/carts/[cartId]/cartlines/add
    A-->>UC: Response
    UC->>S: Update store
    S-->>C: State updated
    C-->>U: UI updated

    alt Authentication Error
        Auth-->>UC: 401 Unauthorized
        UC-->>C: Error
        C-->>U: Login redirect
    else Validation Error
        A-->>UC: 400 Bad Request
        UC-->>C: Error
        C-->>U: Error message
    else Stock Error
        A-->>UC: 412 Precondition Failed
        UC-->>C: Error
        C-->>U: Insufficient stock message
    end

Call Parameters

Main Interface

interface AddOrUpdateCartLineRequest {
  cartId: string; // Cart ID
  typeId: string; // Identifier type ('offerPriceId' or 'productVariantId')
  currency: string; // Currency
  lines: Array<{
    // Lines to add/update
    variantId?: string; // Variant ID (if typeId = 'productVariantId')
    offerPriceId?: string; // Offer ID (if typeId = 'offerPriceId')
    quantity: number; // Quantity
    updateAction: UpdateCartLineType; // Update type
  }>;
}

Update Types

type UpdateCartLineType =
  | 'ADD_QUANTITY' // Add specified quantity
  | 'REMOVE_QUANTITY' // Remove specified quantity
  | 'REPLACE_QUANTITY'; // Replace existing quantity

Detailed Parameters

ParameterTypeRequiredDefault ValueImpact
cartIdstringYes-Identifies the cart to modify
typeIdstringYes-Determines the identifier type to use
currencystringYes-Currency for price calculations
linesArrayYes-List of modifications to apply
variantIdstringConditional-Variant ID (if typeId = 'productVariantId')
offerPriceIdstringConditional-Offer ID (if typeId = 'offerPriceId')
quantitynumberYes-Quantity to add/modify
updateActionUpdateCartLineTypeYes-Type of modification to apply

Call Example

const response = await addOrUpdateCartLine({
  cartId: 'cart-123',
  typeId: 'offerPriceId',
  currency: 'EUR',
  lines: [
    {
      offerPriceId: 'offer-456',
      quantity: 2,
      updateAction: 'REPLACE_QUANTITY',
    },
  ],
});

Composable Returns

Response Interface

interface UpdateCartLinesResponse {
  success: boolean; // Indicates if the update was successful
  message: string; // Confirmation or error message
  cartLines?: CartLine[]; // Updated lines
}

interface CartLine {
  id: string; // Line ID
  offerPriceId: string; // Offer ID
  quantity: number; // Updated quantity
  price: {
    // Offer price
    amount: number; // Amount
    currency: string; // Currency
  };
}

Success Response Format

{
  "success": true,
  "message": "Cart lines added or updated successfully",
  "cartLines": [
    {
      "id": "line-123",
      "offerPriceId": "offer-456",
      "quantity": 2,
      "price": {
        "amount": 19.99,
        "currency": "EUR"
      }
    }
  ]
}

Error Handling

Error Types

CodeCauseActionMessage
401Not authenticatedLogin redirect"Not authenticated"
400Invalid dataError message"Invalid data"
404Cart not foundCarts redirect"Cart not found"
412Insufficient stockError message"Insufficient stock"
500Server errorError message"Server error"

Error Response Format

{
  "success": false,
  "message": "Specific error message",
  "error": {
    "statusCode": 400,
    "message": "Error details"
  }
}

Error Handling Example

try {
  const response = await addOrUpdateCartLine({
    cartId: 'cart-123',
    typeId: 'offerPriceId',
    currency: 'EUR',
    lines: [
      {
        offerPriceId: 'offer-456',
        quantity: 2,
        updateAction: 'REPLACE_QUANTITY',
      },
    ],
  });
} catch (error) {
  switch (error.statusCode) {
    case 401:
      router.push('/auth/login');
      break;
    case 404:
      router.push('/carts');
      break;
    case 400:
      showNotification('Invalid data', 'error');
      break;
    case 412:
      showNotification('Insufficient stock', 'error');
      break;
    default:
      showNotification('An error occurred', 'error');
  }
}

Use Cases

  1. Product Addition

    • Adding a new product to the cart
    • Adding multiple products in a single operation
    • Managing initial quantities
  2. Product Updates

    • Modifying existing quantities
    • Bulk updating multiple products
    • Stock synchronization
  3. Variant Management

    • Adding products by variant
    • Updating existing variants
    • Managing stock by variant

Important Points

Performance

  • Optimized Pinia store updates
  • Efficient error handling
  • Response caching

Security

  • Authentication verification
  • Data validation
  • Injection protection

Flexibility

  • Support for different identifier types
  • Error case handling
  • Business needs adaptation

Integration

  • Compatible with existing cart system
  • Authentication system integration
  • Notification system support

Technical Implementation

/**
 * Adds or updates lines in the cart
 * @param params - Request parameters
 * @param params.cartId - Cart ID
 * @param params.typeId - Identifier type ('offerPriceId' or 'productVariantId')
 * @param params.currency - Currency
 * @param params.lines - Lines to add/update
 * @param useStore - If true, updates the Pinia store
 * @returns Promise<UpdateCartLinesResponse | null>
 * @throws {ApiError} - Error if request fails
 */
export const useCart = () => {
  const addOrUpdateCartLine = async (
    params: AddOrUpdateCartLineRequest,
    useStore = true
  ): Promise<UpdateCartLinesResponse | null> => {
    try {
      await ensureAuthenticated();

      const { data, error } = await useFetch<UpdateCartLinesResponse>(
        `/api/carts/${params.cartId}/cartlines/add`,
        {
          method: 'PUT',
          body: params,
          key: `addOrUpdateCartLine-${params.cartId}`,
        }
      );

      if (error.value) {
        handleError(error.value);
      }

      if (useStore && data.value) {
        updateStore(data.value);
      }

      return data.value || null;
    } catch (e) {
      handleError(e);
    }
  };

  return {
    addOrUpdateCartLine,
  };
};

Execution Flow

  1. Authentication Check
await ensureAuthenticated();
  1. Parameter Validation
if (!params.cartId || !params.typeId || !params.lines?.length) {
  throw new Error('Invalid parameters');
}
  1. API Call
const { data, error } = await useFetch<UpdateCartLinesResponse>(
  `/api/carts/${params.cartId}/cartlines/add`,
  {
    method: 'PUT',
    body: params,
  }
);
  1. Response Handling
if (useStore && data.value) {
  cartStore.cartLines = data.value.cartLines;
}
  1. Error Handling
if (error.value) {
  handleError(error.value);
}