Giỏ hàng của người dùng được truy xuất qua nhóm API /api/v1/shopping-cart. Các API này yêu cầu người dùng đã đăng nhập, vì hệ thống lấy giỏ hàng theo userId của phiên hiện tại.

Lấy Số Lượng Sản Phẩm Trong Giỏ

Dùng API này để hiển thị badge số lượng trên icon giỏ hàng ở header.
GET /api/v1/shopping-cart/product-count
Response:
{
  "count": 2
}
Lưu ý: count là số dòng sản phẩm trong giỏ, không phải tổng quantity. Ví dụ một dòng sản phẩm có amount = 3 vẫn được tính là 1. Nếu muốn hiển thị tổng số lượng item thực tế, hãy gọi API lấy giỏ hàng rồi cộng amount của từng sản phẩm.
Ví dụ JavaScript:
async function fetchShoppingCartProductCount() {
  const response = await fetch('/api/v1/shopping-cart/product-count');

  if (!response.ok) {
    throw new Error('Can not fetch shopping cart product count');
  }

  const data = await response.json();
  return data.count;
}

fetchShoppingCartProductCount()
  .then(count => {
    document.querySelectorAll('.shopping-cart-product-count')
      .forEach(element => {
        element.textContent = count;
      });
  });

Lấy Danh Sách Sản Phẩm Trong Giỏ

Dùng API này khi cần render dropdown mini-cart, trang giỏ hàng bằng frontend, hoặc đồng bộ lại UI sau khi thêm/xóa/cập nhật sản phẩm.
GET /api/v1/shopping-cart?currencyId={currencyId}
Tham số:
TênKiểuÝ nghĩa
currencyIdlongID tiền tệ dùng để format giá sản phẩm và tổng tiền. Nên truyền currency đang được chọn trên giao diện.
Ví dụ:
GET /api/v1/shopping-cart?currencyId=1
Response rút gọn:
{
  "id": 1001,
  "products": [
    {
      "id": 501,
      "product": {
        "id": 12,
        "productName": "Sample Product",
        "productCode": "SP001",
        "iconImage": {
          "id": 10,
          "name": "sample.png"
        },
        "price": "120000",
        "formattedPrice": "120,000",
        "formattedPriceIncludeIsoCode": "120,000 VND",
        "formattedPriceIncludeSymbol": "120,000 ₫",
        "discountPercent": 10,
        "status": "ACTIVATED"
      },
      "amount": 2,
      "totalAmountMoney": 240000,
      "formattedTotalAmountMoney": "240,000",
      "formattedTotalAmountMoneyIncludeIsoCode": "240,000 VND",
      "formattedTotalAmountMoneyIncludeSymbol": "240,000 ₫",
      "size": null,
      "color": null,
      "material": null,
      "deliveryRequired": true
    }
  ],
  "totalAmountMoney": "240000",
  "formattedTotalAmountMoney": "240,000",
  "formattedTotalAmountMoneyIncludeIsoCode": "240,000 VND",
  "formattedTotalAmountMoneyIncludeSymbol": "240,000 ₫",
  "containsDeliveryRequiredProduct": true,
  "createdAt": 1710000000000,
  "updatedAt": 1710000000000
}
Các field quan trọng cho giao diện:
FieldÝ nghĩa
productsDanh sách dòng sản phẩm trong giỏ.
products[].idID dòng sản phẩm trong giỏ, dùng khi cập nhật/xóa dòng đó.
products[].productThông tin sản phẩm gốc: tên, mã, ảnh, giá, trạng thái.
products[].amountSố lượng của dòng sản phẩm.
products[].totalAmountMoneyThành tiền của dòng sản phẩm.
products[].size, color, materialBiến thể sản phẩm nếu có.
totalAmountMoneyTổng tiền giỏ hàng dạng số chuỗi.
formattedTotalAmountMoneyIncludeSymbolTổng tiền đã format kèm ký hiệu tiền tệ, nên dùng để hiển thị.
containsDeliveryRequiredProductCho biết giỏ hàng có sản phẩm cần giao hàng hay không.

Ví Dụ Render Mini Cart

async function fetchShoppingCart(currencyId) {
  const response = await fetch(`/api/v1/shopping-cart?currencyId=`);

  if (!response.ok) {
    throw new Error('Can not fetch shopping cart');
  }

  return response.json();
}

function renderMiniCart(cart) {
  const listElement = document.querySelector('#miniCartProducts');
  const totalElement = document.querySelector('#miniCartTotal');

  listElement.innerHTML = cart.products.map(item => `
    <div class="mini-cart-item">
      <img src="" alt="">
      <div>
        <div></div>
        <div> x </div>
      </div>
      <strong></strong>
    </div>
  `).join('');

  totalElement.textContent = cart.formattedTotalAmountMoneyIncludeSymbol;
}

fetchShoppingCart(1)
  .then(renderMiniCart)
  .catch(() => {
    document.querySelector('#miniCartProducts').innerHTML = '';
    document.querySelector('#miniCartTotal').textContent = '';
  });

Gợi Ý Tích Hợp UI

  • Header badge: gọi /api/v1/shopping-cart/product-count sau khi trang load và sau mỗi thao tác thêm/xóa sản phẩm.
  • Mini-cart hoặc trang giỏ hàng động: gọi /api/v1/shopping-cart?currencyId=....
  • Nếu muốn hiển thị tổng quantity thực tế, dùng:
const totalQuantity = cart.products.reduce(
  (sum, item) => sum + Number(item.amount || 0),
  0
);
  • Nếu API lấy giỏ hàng trả lỗi do chưa có giỏ hàng hiện tại, frontend nên hiển thị trạng thái giỏ hàng rỗng.
  • Các giá trị formatted...IncludeSymbol phù hợp để hiển thị trực tiếp; các giá trị số như totalAmountMoney phù hợp để tính toán.