Strona szczegółów produktu
Dowiedz się, jak zbudować stronę szczegółów produktu, pobierać dane produktu, wyświetlać zdjęcia, formatować ceny i dodawać produkty do zamówienia.
Strona szczegółów produktu (często nazywana skrótowo PDP — Product Detail Page) to strona, która pokazuje szczegóły produktu i umożliwia użytkownikowi dodanie go do koszyka.
Zazwyczaj strona PDP powinna zawierać:
- Nazwę produktu
- Opis produktu
- Dostępne warianty produktu
- Zdjęcia produktu i jego wariantów
- Informacje o cenie
- Informacje o stanie magazynowym
- Przycisk dodawania do koszyka
Pobieranie danych produktu
Stwórzmy zapytanie do pobrania wymaganych danych. Powinieneś mieć dostępny slug lub id produktu z adresu URL. W tym przykładzie użyjemy slug.
query GetProductDetail($slug: String!) {
product(slug: $slug) {
id
name
description
featuredAsset {
id
preview
}
assets {
id
preview
}
variants {
id
name
sku
stockLevel
currencyCode
price
priceWithTax
featuredAsset {
id
preview
}
assets {
id
preview
}
}
}
}{
"slug": "laptop"
}{
"data": {
"product": {
"id": "1",
"name": "Laptop",
"description": "Now equipped with seventh-generation Intel Core processors, Laptop is snappier than ever. From daily tasks like launching apps and opening files to more advanced computing, you can power through your day thanks to faster SSDs and Turbo Boost processing up to 3.6GHz.",
"featuredAsset": {
"id": "1",
"preview": "https://demo.deenruv.com/assets/preview/71/derick-david-409858-unsplash__preview.jpg"
},
"assets": [
{
"id": "1",
"preview": "https://demo.deenruv.com/assets/preview/71/derick-david-409858-unsplash__preview.jpg"
}
],
"variants": [
{
"id": "1",
"name": "Laptop 13 inch 8GB",
"sku": "L2201308",
"stockLevel": "IN_STOCK",
"currencyCode": "USD",
"price": 129900,
"priceWithTax": 155880,
"featuredAsset": null,
"assets": []
},
{
"id": "2",
"name": "Laptop 15 inch 8GB",
"sku": "L2201508",
"stockLevel": "IN_STOCK",
"currencyCode": "USD",
"price": 139900,
"priceWithTax": 167880,
"featuredAsset": null,
"assets": []
},
{
"id": "3",
"name": "Laptop 13 inch 16GB",
"sku": "L2201316",
"stockLevel": "IN_STOCK",
"currencyCode": "USD",
"price": 219900,
"priceWithTax": 263880,
"featuredAsset": null,
"assets": []
},
{
"id": "4",
"name": "Laptop 15 inch 16GB",
"sku": "L2201516",
"stockLevel": "IN_STOCK",
"currencyCode": "USD",
"price": 229900,
"priceWithTax": 275880,
"featuredAsset": null,
"assets": []
}
]
}
}
}To pojedyncze zapytanie dostarcza wszystkie dane potrzebne do wyświetlenia naszej strony PDP.
Formatowanie cen
Jak wyjaśniono w przewodniku o walutach i pieniądzach, ceny są zwracane jako liczby całkowite w najmniejszej jednostce waluty (np. grosze dla PLN, centy dla USD). Dlatego przy wyświetlaniu ceny musimy podzielić ją przez 100 i sformatować zgodnie z zasadami formatowania danej waluty.
W demo na końcu tego przewodnika użyjemy funkcji formatCurrency, która korzysta z API Intl przeglądarki do formatowania ceny zgodnie z lokalizacją użytkownika.
Wyświetlanie zdjęć
Jeśli używamy AssetServerPlugin do serwowania zdjęć produktów (co jest domyślne), możemy skorzystać z możliwości dynamicznej transformacji obrazów, aby wyświetlać zdjęcia produktów w odpowiednim rozmiarze i w zoptymalizowanym formacie, takim jak WebP.
Odbywa się to przez dodanie parametrów do adresu URL obrazu. Na przykład, jeśli chcemy użyć presetu rozmiaru 'large' (800 x 800) i przekonwertować format na WebP, użyjemy adresu URL takiego jak ten:
<img src={product.featuredAsset.preview + '?preset=large&format=webp'} />Jeszcze bardziej zaawansowanym podejściem byłoby wykorzystanie elementu HTML <picture> do dostarczenia wielu źródeł obrazów, aby przeglądarka mogła wybrać optymalny format. Można to opakować w komponent, aby ułatwić użycie. Na przykład:
interface VendureAssetProps {
preview: string;
preset: 'tiny' | 'thumb' | 'small' | 'medium' | 'large';
alt: string;
}
export function VendureAsset({ preview, preset, alt }: VendureAssetProps) {
return (
<picture>
<source type="image/avif" srcSet={preview + `?preset=${preset}&format=avif`} />
<source type="image/webp" srcSet={preview + `?preset=${preset}&format=webp`} />
<img src={preview + `?preset=${preset}&format=jpg`} alt={alt} />
</picture>
);
}Dodawanie do zamówienia
Aby dodać konkretny wariant produktu do zamówienia, musimy wywołać mutację addItemToOrder.
Ta mutacja przyjmuje productVariantId i quantity jako argumenty.
mutation AddItemToOrder($variantId: ID!, $quantity: Int!) {
addItemToOrder(productVariantId: $variantId, quantity: $quantity) {
__typename
...UpdatedOrder
... on ErrorResult {
errorCode
message
}
... on InsufficientStockError {
quantityAvailable
order {
...UpdatedOrder
}
}
}
}
fragment UpdatedOrder on Order {
id
code
state
totalQuantity
totalWithTax
currencyCode
lines {
id
unitPriceWithTax
quantity
linePriceWithTax
productVariant {
id
name
}
}
}{
"variantId": "4",
"quantity": 1
}{
"data": {
"addItemToOrder": {
"__typename": "Order",
"id": "5",
"code": "KE5FJPVV3Y3LX134",
"state": "AddingItems",
"totalQuantity": 1,
"totalWithTax": 275880,
"lines": [
{
"id": "14",
"unitPriceWithTax": 275880,
"quantity": 1,
"linePriceWithTax": 275880
}
]
}
}
}Jest kilka ważnych rzeczy do zapamiętania na temat tej mutacji:
- Ponieważ mutacja
addItemToOrderzwraca typ unii, musimy użyć fragmentu do określenia pól, które chcemy otrzymać. W tym przypadku zdefiniowaliśmy fragment o nazwieUpdatedOrder, który zawiera interesujące nas pola. - Jeśli wystąpią jakiekolwiek oczekiwane błędy, mutacja zwróci obiekt
ErrorResult. Będziemy mogli zobaczyć polaerrorCodeimessagew odpowiedzi, dzięki czemu możemy wyświetlić użytkownikowi zrozumiały komunikat o błędzie. - W specjalnym przypadku
InsufficientStockError, oprócz pólerrorCodeimessage, otrzymujemy także polequantityAvailable, które informuje nas, ile sztuk z żądanej ilości jest dostępnych (i zostało dodanych do zamówienia). To przydatna informacja do wyświetlenia użytkownikowi. ObiektInsufficientStockErrorzawiera również zaktualizowany obiektOrder, którego możemy użyć do aktualizacji interfejsu. - Pole
__typenamemoże być użyte przez klienta do określenia, jaki typ obiektu został zwrócony. Jego wartość będzie równa nazwie zwróconego typu. Oznacza to, że możemy sprawdzić, czy__typename === 'Order', aby określić, czy mutacja zakończyła się sukcesem.
Wyświetlanie produktów
Dowiedz się, jak wyświetlać produkty w kolekcjach, implementować wyszukiwanie produktów i używać wyszukiwania fasetowego do filtrowania w sklepie.
Zarządzanie aktywnym zamówieniem
Dowiedz się, jak zarządzać koszykiem, w tym dodawać produkty, usuwać produkty, zmieniać ilości i stosować kody rabatowe.