Przegląd
Dostęp do danych produktów przez dwie metody:getStore()- Zwraca wszystkie produkty w sklepie (zawarte w odpowiedzi sklepu)getProduct()- Pobiera pojedynczy produkt po ID lub sluggetProductReviews()- Pobiera stronicowane recenzje dla produktu
Pobieranie wszystkich produktów
Produkty są zawarte w odpowiedzi sklepu:const response = await komerza.getStore();
if (response.success) {
const products = response.data.products;
products.forEach((product) => {
console.log(product.name, product.variants.length, "wariantów");
});
}
Pobieranie pojedynczego produktu
Pobierz produkt po ID lub slug:const response = await komerza.getProduct("product-id-or-slug");
Parametry
Unikalny ID produktu (UUID) lub slug URL
Przykład
// Po ID
const byId = await komerza.getProduct("550e8400-e29b-41d4-a716-446655440000");
// Po slug
const bySlug = await komerza.getProduct("premium-license");
if (bySlug.success) {
const product = bySlug.data;
console.log(product.name);
console.log(product.description);
console.log(product.variants);
}
Obiekt Product
interface Product {
id: string; // Unikalny identyfikator
name: string; // Nazwa produktu
description: string; // Opis (obsługuje markdown)
slug?: string; // Przyjazny dla URL slug
imageNames: string[]; // Nazwy plików obrazów produktu (patrz strona Images)
rating: number; // Średnia ocena recenzji
order: number; // Kolejność wyświetlania
visibility: number; // 0=Publiczny, 1=Niewidoczny, 2=Prywatny
storeId: string; // ID sklepu nadrzędnego
variants: Variant[]; // Warianty produktu
dateCreated: string; // Znacznik czasu ISO 8601
}
Warianty
Każdy produkt ma jeden lub więcej wariantów. Każdy wariant ma własną cenę, stan magazynowy i ustawienia:interface Variant {
id: string; // ID wariantu
name: string; // Nazwa wariantu
productId: string; // ID produktu nadrzędnego
storeId: string; // ID sklepu
cost: number; // Cena w walucie sklepu
stock: number; // Dostępny stan magazynowy
stockMode: number; // Tryb obliczania stanu (patrz poniżej)
minimumQuantity: number; // Minimalna ilość zakupu (domyślnie: 1)
maximumQuantity: number; // Maksymalna ilość zakupu (-1 = nieograniczona)
order: number; // Kolejność wyświetlania
imageNames: string[]; // Nazwy plików obrazów specyficznych dla wariantu
type: number; // 0=Jednorazowy, 1=Subskrypcja
subscriptionPeriod?: string; // Czas trwania subskrypcji jeśli dotyczy
requireDiscordAuthorization: boolean;
dateCreated: string;
}
Tryb obliczania stanu magazynowego
PolestockMode określa sposób obliczania dostępności stanu:
| Wartość | Tryb | Opis |
|---|---|---|
| 0 | Obliczony | Stan jest automatycznie obliczany z dostępnych produktów |
| 1 | Ignorowany | Stan nie jest śledzony — zawsze dostępny |
| 2 | Stały | Stan jest ustawiany ręcznie i dekrementowany przy zakupie |
Wyświetlanie obrazów
imageNames produktów i wariantów zawierają nazwy plików, nie pełne adresy URL. Zobacz stronę Images, aby dowiedzieć się jak konstruować pełne adresy URL.
Wyświetlanie wariantów
async function wyswietlProdukt(productId) {
const [productResponse, formatter] = await Promise.all([
komerza.getProduct(productId),
komerza.createFormatter(),
]);
if (!productResponse.success) return;
const product = productResponse.data;
// Sortuj warianty według kolejności
const variants = product.variants.sort((a, b) => a.order - b.order);
variants.forEach((variant) => {
const price = formatter.format(variant.cost);
const inStock = variant.stockMode === 1 || variant.stock > 0;
console.log(`${variant.name}: ${price}`);
console.log(` Stan: ${inStock ? "Dostępny" : "Brak w magazynie"}`);
console.log(` Min ilość: ${variant.minimumQuantity}`);
console.log(
` Max ilość: ${
variant.maximumQuantity === -1
? "Nieograniczona"
: variant.maximumQuantity
}`,
);
});
}
Wybór wariantu
<select id="variant-select" onchange="updatePrice()">
<!-- Wypełniane dynamicznie -->
</select>
<span id="price"></span>
<button onclick="addToCart()">Dodaj do koszyka</button>
<script>
let currentProduct;
let formatter;
async function loadProduct(productId) {
[{ data: currentProduct }, formatter] = await Promise.all([
komerza.getProduct(productId),
komerza.createFormatter(),
]);
const select = document.getElementById("variant-select");
select.innerHTML = currentProduct.variants
.map(
(v) =>
`<option value="${v.id}">${v.name} - ${formatter.format(
v.cost,
)}</option>`,
)
.join("");
updatePrice();
}
function updatePrice() {
const variantId = document.getElementById("variant-select").value;
const variant = currentProduct.variants.find((v) => v.id === variantId);
document.getElementById("price").textContent = formatter.format(
variant.cost,
);
}
function addToCart() {
const variantId = document.getElementById("variant-select").value;
komerza.addToBasket(currentProduct.id, variantId);
}
</script>
Recenzje produktu
Pobierz stronicowane recenzje dla produktu:const response = await komerza.getProductReviews(productId, page);
Parametry
Unikalny ID produktu
Numer strony (indeksowany od 1)
Zwraca
ZwracaPaginatedApiResponse<Review>:
interface PaginatedApiResponse<Review> {
success: boolean;
pages: number; // Łączna liczba stron
data?: Review[]; // Tablica recenzji
message?: string;
}
interface Review {
id: string;
rating: number; // 1-5 gwiazdek
reason: string; // Tekst recenzji
productId: string;
reply?: string; // Odpowiedź sprzedawcy jeśli jest
dateCreated: string;
}
Wyświetlanie recenzji
async function wyswietlRecenzje(productId, page = 1) {
const response = await komerza.getProductReviews(productId, page);
if (!response.success) return;
const container = document.getElementById("reviews");
container.innerHTML = response.data
.map(
(review) => `
<div class="review">
<div class="rating">${"★".repeat(review.rating)}${"☆".repeat(
5 - review.rating,
)}</div>
<p>${review.reason}</p>
${
review.reply
? `<p class="reply"><strong>Odpowiedź:</strong> ${review.reply}</p>`
: ""
}
<time>${new Date(review.dateCreated).toLocaleDateString()}</time>
</div>
`,
)
.join("");
// Paginacja
if (response.pages > 1) {
container.innerHTML += `
<div class="pagination">
${
page > 1
? `<button onclick="wyswietlRecenzje('${productId}', ${
page - 1
})">Poprzednia</button>`
: ""
}
<span>Strona ${page} z ${response.pages}</span>
${
page < response.pages
? `<button onclick="wyswietlRecenzje('${productId}', ${
page + 1
})">Następna</button>`
: ""
}
</div>
`;
}
}
Obrazy produktu
Obrazy produktu są referencjonowane przez nazwę pliku. Skonstruuj pełny adres URL:function getProductImageUrl(storeId, productId, imageName) {
return `https://cdn.komerza.com/stores/${storeId}/products/${productId}/${imageName}`;
}
// Użycie
const product = response.data;
const imageUrl = getProductImageUrl(
product.storeId,
product.id,
product.imageNames[0],
);
Galeria obrazów
function wyswietlGalerieObrazow(product) {
const gallery = document.getElementById("gallery");
// Użyj obrazów wariantu jeśli dostępne, w przeciwnym razie obrazów produktu
const images =
product.variants[0].imageNames.length > 0
? product.variants[0].imageNames
: product.imageNames;
gallery.innerHTML = images
.map(
(img) => `
<img
src="https://cdn.komerza.com/stores/${product.storeId}/products/${product.id}/${img}"
alt="${product.name}"
loading="lazy"
/>
`,
)
.join("");
}
Obsługa stanu magazynowego
Sprawdź dostępność stanu przed dodaniem do koszyka:function moznaAddacDoKoszyka(variant, quantity) {
// stockMode 1 = Ignorowany (nieograniczony)
if (variant.stockMode === 1) return true;
// Sprawdź dostępny stan
if (variant.stock < quantity) return false;
// Sprawdź limity ilości
if (quantity < variant.minimumQuantity) return false;
if (variant.maximumQuantity !== -1 && quantity > variant.maximumQuantity)
return false;
return true;
}
function getStatusStanu(variant) {
if (variant.stockMode === 1) return "Dostępny";
if (variant.stock === 0) return "Brak w magazynie";
if (variant.stock < 10) return `Tylko ${variant.stock} pozostało`;
return "Dostępny";
}
Pełny przykład
<!DOCTYPE html>
<html>
<head>
<title>Strona produktu</title>
<script src="https://cdn.komerza.com/komerza.min.js"></script>
<style>
.product {
max-width: 600px;
margin: 0 auto;
}
.gallery img {
max-width: 100%;
}
.variants {
margin: 20px 0;
}
.reviews {
margin-top: 40px;
}
.review {
border-bottom: 1px solid #eee;
padding: 15px 0;
}
.rating {
color: gold;
}
</style>
</head>
<body>
<div class="product">
<div id="gallery"></div>
<h1 id="name"></h1>
<p id="description"></p>
<p id="rating"></p>
<div class="variants">
<select id="variant-select"></select>
<span id="price"></span>
<span id="stock"></span>
</div>
<div>
<label
>Ilość: <input type="number" id="quantity" value="1" min="1"
/></label>
<button id="add-btn" onclick="addToCart()">Dodaj do koszyka</button>
</div>
<div class="reviews">
<h2>Recenzje</h2>
<div id="reviews"></div>
</div>
</div>
<script>
komerza.init("your-store-id");
let product;
let formatter;
async function loadProduct(idOrSlug) {
const [productResponse, fmt] = await Promise.all([
komerza.getProduct(idOrSlug),
komerza.createFormatter(),
]);
if (!productResponse.success) {
alert("Produkt nie znaleziony");
return;
}
product = productResponse.data;
formatter = fmt;
// Wyświetl informacje o produkcie
document.getElementById("name").textContent = product.name;
document.getElementById("description").textContent =
product.description;
document.getElementById("rating").textContent =
`Ocena: ${product.rating}★`;
// Wyświetl obrazy
const images = product.imageNames;
document.getElementById("gallery").innerHTML = images
.map(
(img) =>
`<img src="https://cdn.komerza.com/stores/${product.storeId}/products/${product.id}/${img}" />`,
)
.join("");
// Wypełnij warianty
const select = document.getElementById("variant-select");
select.innerHTML = product.variants
.map((v) => `<option value="${v.id}">${v.name}</option>`)
.join("");
select.onchange = updateVariantDisplay;
updateVariantDisplay();
loadReviews(1);
}
function updateVariantDisplay() {
const variantId = document.getElementById("variant-select").value;
const variant = product.variants.find((v) => v.id === variantId);
document.getElementById("price").textContent = formatter.format(
variant.cost,
);
// Status stanu
let stockText = "Dostępny";
if (variant.stockMode !== 1) {
if (variant.stock === 0) stockText = "Brak w magazynie";
else if (variant.stock < 10)
stockText = `Tylko ${variant.stock} pozostało`;
}
document.getElementById("stock").textContent = stockText;
// Zaktualizuj limity ilości
const qtyInput = document.getElementById("quantity");
qtyInput.min = variant.minimumQuantity;
qtyInput.max =
variant.maximumQuantity === -1 ? 999 : variant.maximumQuantity;
qtyInput.value = variant.minimumQuantity;
// Wyłącz przycisk jeśli brak w magazynie
document.getElementById("add-btn").disabled =
variant.stockMode !== 1 && variant.stock === 0;
}
function addToCart() {
const variantId = document.getElementById("variant-select").value;
const quantity = parseInt(document.getElementById("quantity").value);
komerza.addToBasket(product.id, variantId, quantity);
alert("Dodano do koszyka!");
}
async function loadReviews(page) {
const response = await komerza.getProductReviews(product.id, page);
if (!response.success || response.data.length === 0) {
document.getElementById("reviews").innerHTML = "<p>Brak recenzji</p>";
return;
}
document.getElementById("reviews").innerHTML = response.data
.map(
(review) => `
<div class="review">
<div class="rating">${"★".repeat(review.rating)}${"☆".repeat(
5 - review.rating,
)}</div>
<p>${review.reason}</p>
${review.reply ? `<p><em>Odpowiedź: ${review.reply}</em></p>` : ""}
</div>
`,
)
.join("");
}
// Załaduj produkt z URL lub domyślny
const urlParams = new URLSearchParams(window.location.search);
const productId = urlParams.get("product") || "your-default-product-slug";
loadProduct(productId);
</script>
</body>
</html>
Następne kroki
Formatowanie walut
Formatuj ceny w walucie sklepu
Zarządzanie koszykiem
Dodawaj produkty do koszyka