xStore.customer
Dữ liệu riêng của khách đã đăng nhập. Module này chia thành sáu nhóm con: addresses, orders, points, coupons, savedProducts, productViews.
Phương thức
| Phương thức | Cú pháp | Mô tả | Từ phiên bản |
|---|---|---|---|
addresses.list |
xStore.customer.addresses.list(): Promise<CursorPage<CustomerAddress>> |
Danh sách địa chỉ đã lưu. | 1.0 |
addresses.create |
xStore.customer.addresses.create(address): Promise<CustomerAddress> |
Thêm địa chỉ mới. | 1.0 |
addresses.update |
xStore.customer.addresses.update(id, address): Promise<CustomerAddress> |
Sửa một địa chỉ. | 1.0 |
addresses.delete |
xStore.customer.addresses.delete(id): Promise<void> |
Xoá một địa chỉ. | 1.0 |
addresses.setDefault |
xStore.customer.addresses.setDefault(id): Promise<void> |
Đặt một địa chỉ làm mặc định. | 1.0 |
orders.list |
xStore.customer.orders.list({ cursor, limit }) hoặc xStore.customer.orders.list(cursor?, limit = 10): Promise<CursorPage<CustomerOrderListItem>> |
Danh sách đơn hàng của khách, phân trang bằng con trỏ. | 1.0 |
orders.get |
xStore.customer.orders.get(orderId): Promise<OrderDetail> |
Chi tiết một đơn hàng. | 1.0 |
points.get |
xStore.customer.points.get({ cursor, limit }) hoặc xStore.customer.points.get(cursor?, limit = 20): Promise<CustomerPointsRead> |
Số dư điểm thưởng và lịch sử biến động. | 1.0 |
coupons.list |
xStore.customer.coupons.list({ cursor, limit }) hoặc xStore.customer.coupons.list(cursor?, limit = 20): Promise<CursorPage<CustomerCouponUsage>> |
Mã giảm giá khách đang có. | 1.0 |
savedProducts.list |
xStore.customer.savedProducts.list({ cursor, limit }): Promise<CursorPage<SavedProduct>> |
Sản phẩm khách đã lưu. Mỗi dòng chỉ có id, product_id và created_at — KHÔNG kèm thẻ sản phẩm. Gom product_id lại rồi gọi products.list({ ids }) một lần, đừng gọi products.get() trong vòng lặp. | 2.1 |
savedProducts.add |
xStore.customer.savedProducts.add(productId): Promise<void> |
Lưu một sản phẩm vào danh sách yêu thích. | 2.1 |
savedProducts.remove |
xStore.customer.savedProducts.remove(productId): Promise<void> |
Bỏ một sản phẩm khỏi danh sách yêu thích. | 2.1 |
productViews.list |
xStore.customer.productViews.list({ cursor, limit }): Promise<CursorPage<ProductView>> |
Lịch sử xem sản phẩm của CHÍNH khách đang đăng nhập, kèm view_count và last_viewed_at. Khác với recommendations.recentlyViewed(), vốn nhận diện khách vãng lai bằng sessionToken. | 2.1 |
productViews.record |
xStore.customer.productViews.record(productId): Promise<void> |
Ghi nhận khách đã xem một sản phẩm. Cần đăng nhập; khách vãng lai dùng recommendations.recordView(). | 2.1 |
Ví dụ đầy đủ
<script>
// Module này chia thành sáu nhóm con: addresses, orders, points,
// coupons, savedProducts, productViews.
// Mọi hàm đều yêu cầu khách đã đăng nhập — bắt 401 và đưa về trang đăng nhập.
async function renderAddresses() {
try {
const page = await xStore.customer.addresses.list();
document.getElementById('addresses').innerHTML = page.items.map((a) => `
<li>
<strong>${a.recipient_name}</strong> — ${a.phone}<br>
${a.address_line}, ${a.ward}, ${a.district}, ${a.province}
${a.is_default ? '<em>(mặc định)</em>'
: `<button data-set-default="${a.id}">Đặt làm mặc định</button>`}
</li>
`).join('');
} catch (err) {
if (err.status === 401) {
window.location.href = '/dang-nhap?next=' + encodeURIComponent(location.pathname);
}
}
}
document.getElementById('addresses').addEventListener('click', async (e) => {
const id = e.target.dataset.setDefault;
if (!id) return;
await xStore.customer.addresses.setDefault(id);
renderAddresses();
});
// Đơn hàng phân trang bằng con trỏ, không phải số trang.
async function loadMoreOrders(cursor) {
const page = await xStore.customer.orders.list({ cursor, limit: 10 });
return { items: page.items, next: page.next_cursor };
}
// Sản phẩm đã lưu: danh sách chỉ trả về product_id, KHÔNG kèm thẻ sản
// phẩm. Lấy id rồi hydrate một lần bằng products.list({ ids }).
async function renderWishlist() {
const luu = await xStore.customer.savedProducts.list({ limit: 50 });
if (luu.items.length === 0) return;
const the = await xStore.products.list({ ids: luu.items.map((s) => s.product_id) });
document.getElementById('wishlist').innerHTML = the.items.map((p) => `
<li>
<a href="${p.url ?? '#'}">${p.title}</a>
<span>${xStore.utils.formatCurrency(p.effective_price ?? p.price ?? 0)}</span>
<button data-unsave="${p.id}">Bỏ lưu</button>
</li>
`).join('');
}
document.getElementById('wishlist').addEventListener('click', async (e) => {
const id = e.target.dataset.unsave;
if (!id) return;
await xStore.customer.savedProducts.remove(id);
renderWishlist();
});
renderAddresses();
renderWishlist();
</script>
Thư viện gọi tới /api/... trên chính tên miền cửa hàng, nên không cần khai báo địa chỉ máy chủ ở bất kỳ đâu.
Xem thêm Sự kiện để giao diện tự cập nhật sau mỗi thao tác.