From f7969b87e132de09e2da4da63b251cf28a38bb50 Mon Sep 17 00:00:00 2001
From: andr-ew Product not found Scroll to right ( → )
- {availableForSale ? (
- isForSale && (
- <>
- <>
- {onSale && (
-
- {formatPriceRange(compareAtPriceRange)}{' '}
-
- )}
- >
- {formatPriceRange(priceRange)}
- >
- )
- ) : (
- Sold Out
- )}
-
+ {availableForSale ? ( + isForSale && ( + <> + <> + {onSale && ( + + {formatPriceRange( + product?.compareAtPriceRange + )}{' '} + + )} + > + {formatPriceRange(product?.priceRange)} + > + ) + ) : ( + Sold Out + )} +
+ ); +}; + +export const variantAvailableForSale = variant => + variant?.availableForSale ?? false; +export const variantOnSale = variant => + (variant?.compareAtPrice?.amount ?? 0) > (variant?.price?.amount ?? 0); + +export const VariantPrice = ({ variant, quantity }) => { + const availableForSale = variantAvailableForSale(variant); + const onSale = variantOnSale(variant); + + return variant ? ( ++ {formatPrice({ + amount: + (variant?.compareAtPrice?.amount ?? 0) * + quantity, + currencyCode: + variant?.compareAtPrice?.currencyCode, + })} +
+ )} + > ++ {formatPrice({ + amount: (variant?.price?.amount ?? 0) * quantity, + currencyCode: variant?.price?.currencyCode, + })} +
+ > + ) : ( + // TODO: this can just say "Sold Out" in the future +Variant Sold Out
+ )} +Sorry, the price can't be found
+ ); +}; diff --git a/components/product/purchase-input.js b/components/product/purchase-input.js index 212cbc37d..afd14b320 100644 --- a/components/product/purchase-input.js +++ b/components/product/purchase-input.js @@ -1,43 +1,120 @@ 'use client'; +import { useState } from 'react'; +import Link from 'next/link'; + import { Option, Select, NumberInput } from '/components/input.js'; +import { + productAvailableForSale, + productHasOptions, + productIsForSale, + VariantPrice, +} from '/components/price.js'; + +export const productVariant = ({ product, selectedOptions }) => { + const hasOptions = productHasOptions(product); + + if (hasOptions) { + const optionNames = + product?.options?.map(option => option?.name ?? '') ?? []; + + console.log({ + product: product?.handle, + optionNames, + variants: product?.variants, + }); + + for (const variant of product?.variants ?? []) { + let matching = true; + + console.log({ variantTitle: variant?.title }); + + for (const option of variant?.selectedOptions) { + const optionName = option?.name ?? ''; + const optionValue = option?.value ?? ''; + + console.log({ optionName, optionValue, optionNames }); + + for (let i = 0; i < optionNames?.length; i++) { + if (optionName == optionNames[i]) { + console.log({ + optionName, + optionValue, + selectedOption: selectedOptions[i], + }); + + if (optionValue != selectedOptions[i]) { + matching = false; + } + } + } + } + + if (matching) { + return variant; + } + } + } +}; export default function PurchaseInput({ product }) { - const hasOptions = product?.options?.[0]?.values.length > 1 ?? false; - //TODO: turn these checks into shared functions - // const onSale = - // (compareAtPriceRange?.minVariantPrice?.amount ?? 0) > - // (priceRange?.minVariantPrice?.amount ?? 0) || - // (compareAtPriceRange?.maxVariantPrice?.amount ?? 0) > - // (priceRange?.maxVariantPrice?.amount ?? 0); - const isForSale = (product?.priceRange?.maxVariantPrice?.amount ?? 0) > 0; + const hasOptions = productHasOptions(product); + const isForSale = productIsForSale(product); + const availableForSale = productAvailableForSale(product); - return ( - product?.availableForSale && + const [qty, setQty] = useState(1); + + const [selectedOptions, setSelectedOptions] = useState( + product?.options?.map(option => option?.values?.[0] ?? '') ?? [] + ); + + const variant = hasOptions + ? productVariant({ product, selectedOptions }) + : product?.variants?.[0]; + + console.log({ variant }); + + return availableForSale ? ( isForSale && ( <> -Sold Out
); } diff --git a/lib/shopify/fragments/product.ts b/lib/shopify/fragments/product.ts index e6ea44cf4..c4df506ae 100644 --- a/lib/shopify/fragments/product.ts +++ b/lib/shopify/fragments/product.ts @@ -38,6 +38,10 @@ const productFragment = /* GraphQL */ ` amount currencyCode } + compareAtPrice { + amount + currencyCode + } } } } diff --git a/package-lock.json b/package-lock.json index 74feeadb4..eededf34d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "react": "18.2.0", "react-cookie": "^4.1.1", "react-dom": "18.2.0", + "server-only": "^0.0.1", "xss": "^1.0.14" }, "devDependencies": { @@ -5157,6 +5158,11 @@ "node": ">=10" } }, + "node_modules/server-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", + "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", diff --git a/package.json b/package.json index 669b9196f..f56cb15d3 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "react": "18.2.0", "react-cookie": "^4.1.1", "react-dom": "18.2.0", + "server-only": "^0.0.1", "xss": "^1.0.14" }, "devDependencies": {