Sell only available products / fix out of stock

This commit is contained in:
cond0r 2021-03-27 19:09:00 +02:00
parent 81ac0dd1d4
commit c2e5eb8501
8 changed files with 43 additions and 20 deletions

View File

@ -146,8 +146,12 @@ const ProductView: FC<Props> = ({ product }) => {
className={s.button} className={s.button}
onClick={addToCart} onClick={addToCart}
loading={loading} loading={loading}
disabled={variant?.availableForSale === false}
> >
Add to Cart {variant?.isInStock === false &&
variant?.availableForSale === false
? 'Out Of Stock'
: 'Add To Cart'}
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -190,6 +190,12 @@ interface ProductImage {
interface ProductVariant2 { interface ProductVariant2 {
id: string | number id: string | number
options: ProductOption[] options: ProductOption[]
// Indicates whether this product variant is in stock.
isInStock?: boolean
// Indicates if the product variant is available for sale.
availableForSale?: boolean
// The total sellable quantity of the variant for online sales channels.
quantityAvailable?: number
} }
interface ProductPrice { interface ProductPrice {

View File

@ -10,11 +10,14 @@ export const handler: SWRHook<Customer | null> = {
query: getCustomerQuery, query: getCustomerQuery,
}, },
async fetcher({ options, fetch }) { async fetcher({ options, fetch }) {
const customerAccessToken = getCustomerToken()
if (customerAccessToken) {
const data = await fetch<any | null>({ const data = await fetch<any | null>({
...options, ...options,
variables: { customerAccessToken: getCustomerToken() }, variables: { customerAccessToken },
}) })
return data.customer ?? null return data.customer ?? null
}
}, },
useHook: ({ useData }) => (input) => { useHook: ({ useData }) => (input) => {
return useData({ return useData({

View File

@ -18,9 +18,7 @@ export interface LineItem extends Core.LineItem {
* Cart mutations * Cart mutations
*/ */
export type Product = Core.Product & { export type Product = Core.Product
totalInventory?: Maybe<Scalars['Int']>
}
export type OptionSelections = { export type OptionSelections = {
option_id: number option_id: number

View File

@ -7,7 +7,7 @@ export const getSearchVariables = ({
categoryId, categoryId,
sort, sort,
}: SearchProductsInput) => { }: SearchProductsInput) => {
let query = '' let query = 'available_for_sale:true'
if (search) { if (search) {
query += ` product_type:${search} OR title:${search} OR tag:${search}` query += ` product_type:${search} OR title:${search} OR tag:${search}`

View File

@ -51,15 +51,27 @@ const normalizeProductImages = ({ edges }: ImageConnection) =>
const normalizeProductVariants = ({ edges }: ProductVariantConnection) => { const normalizeProductVariants = ({ edges }: ProductVariantConnection) => {
return edges?.map( return edges?.map(
({ ({
node: { id, selectedOptions, sku, title, priceV2, compareAtPriceV2 }, node: {
id,
title,
sku,
priceV2,
compareAtPriceV2,
selectedOptions,
requiresShipping,
availableForSale,
quantityAvailable,
},
}) => { }) => {
return { return {
id, id,
name: title, name: title,
sku: sku ?? id, sku: sku ?? '',
price: +priceV2.amount, price: +priceV2.amount,
listPrice: +compareAtPriceV2?.amount, listPrice: +compareAtPriceV2?.amount,
requiresShipping: true, requiresShipping,
availableForSale,
isInStock: Boolean(Number(quantityAvailable) > 0),
options: selectedOptions.map(({ name, value }: SelectedOption) => { options: selectedOptions.map(({ name, value }: SelectedOption) => {
const options = normalizeProductOption({ const options = normalizeProductOption({
id, id,
@ -84,7 +96,6 @@ export function normalizeProduct(productNode: ShopifyProduct): Product {
handle, handle,
priceRange, priceRange,
options, options,
totalInventory,
...rest ...rest
} = productNode } = productNode
@ -98,7 +109,6 @@ export function normalizeProduct(productNode: ShopifyProduct): Product {
price: money(priceRange?.minVariantPrice), price: money(priceRange?.minVariantPrice),
images: normalizeProductImages(images), images: normalizeProductImages(images),
variants: variants ? normalizeProductVariants(variants) : [], variants: variants ? normalizeProductVariants(variants) : [],
totalInventory,
options: options options: options
? options ? options
.filter((o) => o.name !== 'Title') // By default Shopify adds a 'Title' name when there's only one option. We don't need it. https://community.shopify.com/c/Shopify-APIs-SDKs/Adding-new-product-variant-is-automatically-adding-quot-Default/td-p/358095 .filter((o) => o.name !== 'Title') // By default Shopify adds a 'Title' name when there's only one option. We don't need it. https://community.shopify.com/c/Shopify-APIs-SDKs/Adding-new-product-variant-is-automatically-adding-quot-Default/td-p/358095

View File

@ -10,7 +10,7 @@ edges {
vendor vendor
handle handle
description description
totalInventory availableForSale
priceRange { priceRange {
minVariantPrice { minVariantPrice {
amount amount
@ -48,7 +48,7 @@ products(
const getAllProductsQuery = /* GraphQL */ ` const getAllProductsQuery = /* GraphQL */ `
query getAllProducts( query getAllProducts(
$first: Int = 250 $first: Int = 250
$query: String = "" $query: String = "available_for_sale:true"
$sortKey: ProductSortKeys = RELEVANCE $sortKey: ProductSortKeys = RELEVANCE
$reverse: Boolean = false $reverse: Boolean = false
) { ) {

View File

@ -8,7 +8,6 @@ const getProductQuery = /* GraphQL */ `
vendor vendor
description description
descriptionHtml descriptionHtml
totalInventory
options { options {
id id
name name
@ -34,6 +33,9 @@ const getProductQuery = /* GraphQL */ `
id id
title title
sku sku
availableForSale
requiresShipping
quantityAvailable
selectedOptions { selectedOptions {
name name
value value