Setting the file. One moment.
Use Product Detail · Wix Vibe Headless · wix/skills · Skills Docs
ContentsBack to the top of the page Wix Blog
references/storefront/app/hooks/useProductDetail.js
references/storefront/app/hooks/ useProductDetail.js
JavaScript · 73 lines · 3 KB
useProductDetail
(
slug
) {
11 const { addToCart } = useCart ();
12 const [ product , setProduct ] = useState ( null );
13 const [ notFound , setNotFound ] = useState ( false );
14 const [ selectedOptions , setSelectedOptions ] = useState ({});
15 const [ modifierValues , setModifierValues ] = useState ({});
16 const [ quantity , setQuantity ] = useState ( 1 );
17
18 useEffect (() => {
19 getProductBySlug (slug). then (( p ) => {
20 if ( ! p) return setNotFound ( true );
21 setProduct (p);
22 const initial = {};
23 (p.options || []). forEach (( o ) => {
24 const first = o.choicesSettings?.choices?. find (( c ) => c.inStock !== false );
25 if (first) initial[o.id] = first.choiceId;
26 });
27 setSelectedOptions (initial);
28 });
29 }, [slug]);
30
31 const options = product?.options || [];
32 const modifiers = product?.modifiers || [];
33 const variants = product?.variantsInfo?.variants || [];
34
35 const variant = useMemo (() => {
36 if (options. length === 0 ) return variants[ 0 ] || null ;
37 if ( ! options. every (( o ) => selectedOptions[o.id])) return null ;
38 return variants. find (( v ) => (v.choices || []). every (( c ) =>
39 selectedOptions[c.optionChoiceIds?.optionId] === c.optionChoiceIds?.choiceId)) || null ;
40 }, [options, variants, selectedOptions]);
41
42 const inStock = variant ? variant.inventoryStatus?.inStock !== false : true ;
43 const canAdd = useMemo (() => {
44 if (options. length > 0 && ! variant) return false ;
45 if (variant && ! inStock) return false ;
46 return modifiers. filter (( m ) => m.mandatory). every (( m ) =>
47 m.modifierRenderType === "FREE_TEXT" ? !! modifierValues[m.freeTextSettings?.key] : !! modifierValues[m.key]);
48 }, [options, variant, inStock, modifiers, modifierValues]);
49
50 const price = variant?.price?.actualPrice?.formattedAmount || product?.actualPriceRange?.minValue?.formattedAmount || "" ;
51
52 const selectOption = ( optionId , choiceId ) => setSelectedOptions (( s ) => ({ ... s, [optionId]: choiceId }));
53 const setModifier = ( key , value ) => setModifierValues (( s ) => ({ ... s, [key]: value }));
54
55 async function submit () {
56 const modifierChoices = {}, customTextFields = {};
57 modifiers. forEach (( m ) => {
58 const k = m.modifierRenderType === "FREE_TEXT" ? m.freeTextSettings?.key : m.key;
59 if ( ! k || ! modifierValues[k]) return ;
60 (m.modifierRenderType === "FREE_TEXT" ? customTextFields : modifierChoices)[k] = modifierValues[k];
61 });
62 await addToCart (product.id, variant?.id, quantity, {
63 modifierChoices: Object. keys (modifierChoices). length ? modifierChoices : undefined ,
64 customTextFields: Object. keys (customTextFields). length ? customTextFields : undefined ,
65 });
66 }
67
68 return {
69 product, notFound, options, modifiers,
70 selectedOptions, selectOption, modifierValues, setModifier,
71 quantity, setQuantity, variant, inStock, canAdd, price, submit,
72 };
73 }