Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions src/lib/components/Product.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@
export let priceOverride = null;

export let VariantSelector = null;

// Per-variant timeline override carried by VariantSelector (e.g., harness
// JSON overrides like Tesla B's "4-8 weeks"). Treated as the authoritative
// backorder signal when present — shown regardless of Shopify stock state.
let variantBackordered = null;
function handleVariantSelection(variant) {
selectedVariantId = variant?.id || null;
backordered = variant?.currentlyNotInStock ? (variant.backordered || '1-12 weeks') : null;
variantBackordered = variant?.backordered || null;
}

let currentImageIndex = 0;
Expand Down Expand Up @@ -72,17 +77,23 @@
}
}

// Priority: static prop > per-variant JSON override (always shown) >
// Shopify-driven default ('1-12 weeks' when currentlyNotInStock).
$: effectiveBackordered = backordered
|| variantBackordered
|| (selectedVariant?.currentlyNotInStock ? '1-12 weeks' : null);

let addToCartLabel;
$: {
if (disableBuyButtonText) {
addToCartLabel = disableBuyButtonText;
} else if (forceOutOfStock || (selectedVariant && !selectedVariant.availableForSale)) {
addToCartLabel = "Out of stock";
if (backordered) {
addToCartLabel += ` (${backorderedPrefix}${backordered})`;
if (effectiveBackordered) {
addToCartLabel += ` (${backorderedPrefix}${effectiveBackordered})`;
}
} else if (backordered) {
addToCartLabel = `Add to cart (${backorderedPrefix}${backordered})`;
} else if (effectiveBackordered) {
addToCartLabel = `Add to cart (${backorderedPrefix}${effectiveBackordered})`;
} else {
addToCartLabel = "Add to cart";
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/ProductDescriptions/CommaFour.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
backordered = null;
disableBuyButtonText = null;
} else if (value) {
backordered = value.currentlyNotInStock ? (value.backordered || '1-12 weeks') : null;
backordered = value.backordered || (value.currentlyNotInStock ? '1-12 weeks' : null);
disableBuyButtonText = null;
} else {
backordered = null;
Expand Down
1 change: 1 addition & 0 deletions src/lib/data/products.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ export const products = {
"harness-connector": {
title: "harness connector",
id: "gid://shopify/Product/4310075310143",
inventoryFromProductId: "gid://shopify/Product/4447447908415", // shares physical inventory with car-harness; matched by variant title
route: "/shop/harness-connector",
category: "accessories",
price: "$50",
Expand Down
26 changes: 24 additions & 2 deletions src/routes/shop/[product]/+page.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,33 @@ export async function load({ url, params }) {
}
}

// Fetch from Shopify
const response = await getProduct(productInfo.id);
// Fetch from Shopify (in parallel with optional sibling for inventory overlay)
const [response, sourceResponse] = await Promise.all([
getProduct(productInfo.id),
productInfo.inventoryFromProductId ? getProduct(productInfo.inventoryFromProductId) : Promise.resolve(null),
]);
if (response.status === 200) {
const product = response.body?.data?.product;
if (product) {
// TODO: remove and use product bundles
// When this product shares physical stock with another Shopify product,
// overlay the sibling's inventory flags onto our variants by title match.
if (sourceResponse?.status === 200) {
const sourceVariants = sourceResponse.body?.data?.product?.variants?.nodes || [];
const sourceByTitle = new Map(sourceVariants.map(v => [v.title, v]));
product.variants = {
...product.variants,
nodes: (product.variants?.nodes || []).map(v => {
const source = sourceByTitle.get(v.title);
if (!source) return v;
return {
...v,
currentlyNotInStock: source.currentlyNotInStock,
availableForSale: source.availableForSale,
};
}),
};
}
return {
product: {
...product,
Expand Down
Loading