@godaddy/gd-commerce-storefront 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +34 -7
- package/docs/server-api.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -165,7 +165,7 @@ Add your own elements between parts, reorder them, or leave out display parts. `
|
|
|
165
165
|
| `ProductDetailsAvailability` | Stock for the verified SKU; nothing before verification |
|
|
166
166
|
| `ProductDetailsAddToCart` | Adds the verified SKU and quantity, labeled with the total, such as "Add to cart · $64.00". Until every option is chosen it names the next one, such as "Select size", and pressing it shows an error on each missing option and focuses the first. While a selection is checked or unavailable, it is disabled and its accessible description gives the reason |
|
|
167
167
|
|
|
168
|
-
Values whose SKUs are all sold out, given the shopper's other selections, are crossed out and announced as "sold out", but stay selectable, so the shopper can change options in any order.
|
|
168
|
+
Values that no active SKU has are left out, so every value shown can be bought, and a link that names one is treated as if that option is not chosen. An attribute that no SKU has a value for keeps all its values. Values whose SKUs are all sold out, given the shopper's other selections, are crossed out and announced as "sold out", but stay selectable, so the shopper can change options in any order. Both need every SKU with its attribute values in the product response, which `@godaddy/gd-commerce-server` returns for up to 50 SKUs; for a product with more, every value is shown, none is marked, and the add button still says "Out of stock" once a sold-out SKU is chosen.
|
|
169
169
|
|
|
170
170
|
Every part is named `ProductDetails*` because it works only inside `ProductDetailsRoot`. `AddToCartButton` is the standalone button for a SKU you already have.
|
|
171
171
|
|
package/dist/index.js
CHANGED
|
@@ -2351,11 +2351,14 @@ function ProductDetailsLoader({ productId, className, children, urlState = true,
|
|
|
2351
2351
|
});
|
|
2352
2352
|
const productNotFound = product.isError && product.error instanceof ApiError && product.error.status === 404;
|
|
2353
2353
|
const group = product.data?.skuGroup;
|
|
2354
|
-
const attributes = getProductAttributes(group);
|
|
2354
|
+
const attributes = getOfferedAttributes(group, getProductAttributes(group));
|
|
2355
2355
|
const skuOptions = getLabeledSkuOptions(group);
|
|
2356
2356
|
const explicitSku = skuOptions.find((sku) => sku.id === params.get("sku"));
|
|
2357
|
-
const selections = attributes.map((attribute) =>
|
|
2358
|
-
|
|
2357
|
+
const selections = attributes.map((attribute) => {
|
|
2358
|
+
const value$1 = params.get(`option.${attribute.name}`) ?? "";
|
|
2359
|
+
return attribute.values.some((candidate) => candidate.name === value$1) ? value$1 : "";
|
|
2360
|
+
});
|
|
2361
|
+
const complete = skuOptions.length > 0 ? !!explicitSku : selections.every(Boolean);
|
|
2359
2362
|
const selectionParams = new URLSearchParams();
|
|
2360
2363
|
selections.filter(Boolean).forEach((value$1) => {
|
|
2361
2364
|
selectionParams.append("attributeValues", value$1);
|
|
@@ -2485,15 +2488,39 @@ function ProductDetailsLoader({ productId, className, children, urlState = true,
|
|
|
2485
2488
|
function focusFirstMissing(root) {
|
|
2486
2489
|
root.current?.querySelector("[data-commerce-missing] input:not(:disabled), [data-commerce-missing] select")?.focus();
|
|
2487
2490
|
}
|
|
2491
|
+
function getSkuAttributeValues(group) {
|
|
2492
|
+
const connection = group?.skus;
|
|
2493
|
+
const skus = connection?.edges?.flatMap((edge) => edge?.node ? [edge.node] : []) ?? [];
|
|
2494
|
+
const values = skus.map(getSkuAttributeValueNames);
|
|
2495
|
+
return {
|
|
2496
|
+
skus,
|
|
2497
|
+
values,
|
|
2498
|
+
complete: !connection?.pageInfo?.hasNextPage && (connection?.totalCount ?? skus.length) === skus.length && values.every((names) => names !== null)
|
|
2499
|
+
};
|
|
2500
|
+
}
|
|
2501
|
+
/**
|
|
2502
|
+
* The attributes with only the values some active SKU has, so a shopper is never offered a value that cannot be
|
|
2503
|
+
* bought. Needs every SKU with its attribute values, so it keeps every value for a truncated list or an older
|
|
2504
|
+
* server. An attribute that no SKU has a value for keeps every value, so its control still renders.
|
|
2505
|
+
*/
|
|
2506
|
+
function getOfferedAttributes(group, attributes) {
|
|
2507
|
+
const { values, complete } = getSkuAttributeValues(group);
|
|
2508
|
+
if (!complete) return attributes;
|
|
2509
|
+
const offered = new Set(values.flatMap((names) => names ?? []));
|
|
2510
|
+
return attributes.map((attribute) => {
|
|
2511
|
+
const kept = attribute.values.filter((value) => offered.has(value.name));
|
|
2512
|
+
return kept.length ? {
|
|
2513
|
+
...attribute,
|
|
2514
|
+
values: kept
|
|
2515
|
+
} : attribute;
|
|
2516
|
+
});
|
|
2517
|
+
}
|
|
2488
2518
|
/**
|
|
2489
2519
|
* For each attribute, the values whose every SKU, among those with the other selected values, has tracked stock
|
|
2490
2520
|
* used up. Needs every SKU with its attribute values, so it is empty for a truncated list or an older server.
|
|
2491
2521
|
*/
|
|
2492
2522
|
function getSoldOutValues(group, attributes, selections) {
|
|
2493
|
-
const
|
|
2494
|
-
const skus = connection?.edges?.flatMap((edge) => edge?.node ? [edge.node] : []) ?? [];
|
|
2495
|
-
const values = skus.map(getSkuAttributeValueNames);
|
|
2496
|
-
const complete = !connection?.pageInfo?.hasNextPage && (connection?.totalCount ?? skus.length) === skus.length && values.every((names) => names !== null);
|
|
2523
|
+
const { skus, values, complete } = getSkuAttributeValues(group);
|
|
2497
2524
|
return attributes.map((attribute, index) => {
|
|
2498
2525
|
const soldOut = /* @__PURE__ */ new Set();
|
|
2499
2526
|
if (!complete) return soldOut;
|
package/docs/server-api.md
CHANGED
|
@@ -68,7 +68,7 @@ Exported `SKUGroup`, `SKU`, `Connection`, `SkuGroupsResult` and `SkuGroupResult`
|
|
|
68
68
|
|
|
69
69
|
For options, return `attributes.edges[].node` with `name`, `label`, and `values.edges[].node` containing `name` and `label`. For example, the attribute `color` has values named `blue` and `clay`. The browser sends those value names as repeated `attributeValues` parameters. Return the group with a SKU connection filtered to that exact combination. Zero or multiple results cannot be purchased. Include accurate `totalCount` and `hasNextPage`; a truncated one-item result must never look like a complete match.
|
|
70
70
|
|
|
71
|
-
Optionally, give each SKU in the unfiltered response its `attributeValues.edges[].node.name`. With every SKU and its value names, the product page crosses out values whose SKUs are all sold out, given the shopper's other selections. Without them, or when `hasNextPage` is true,
|
|
71
|
+
Optionally, give each SKU in the unfiltered response its `attributeValues.edges[].node.name`. With every SKU and its value names, the product page leaves out values that no SKU has and crosses out values whose SKUs are all sold out, given the shopper's other selections. Without them, or when `hasNextPage` is true, every value is shown and none is marked sold out; the add button still reports a sold-out SKU once it is chosen.
|
|
72
72
|
|
|
73
73
|
Products without attribute definitions can offer explicit SKU selection only when all SKUs are returned with unique IDs and unique nonempty labels/names. Ambiguous or incomplete collections cannot be purchased. No inventory records means untracked inventory; records without an `AVAILABLE` quantity mean unavailable. Supply appropriate records for physical inventory.
|
|
74
74
|
|