'Get available combinations by checking quantity from selected variants

I am working on a project where each product has variants like (size, color). The user when selecting a product who have variants sees a modal like below, to choose the desired color and desired size.

Variants

My logic is when the user selects a variant, for example, Red color, the id for this variant is saved into colorId state. same for size variants. then when we have colorId and sizeId, these ids are shapes the combinations ids which are already saved into a separate JSON object called combinations.

then to check for available combinations for example (Red/Large) we should compare the colorId/sizeId with combination ids which holds [colorId,sizeId] and get the quantity for this combination and update the disabled array with the combination id to disable that variant from showing up when user clicks on color first or size first.

my code is:

  const getAvailableCombinations = () => {
    setDisabled([]);
    let sizeIds = [];
    //get all size Ids avalaibe for this product
    product.variants.map(
      (opt) =>
        opt.type === 'size' &&
        opt.values.map((val) => {
          return sizeIds.push(val.id);
        })
    );

    for (let i = 0; i < sizeIds.length; i++) {
      product.combinations.find((combo) => {
        if (
          combo.ids.join('') === `${colorId + sizeIds[i]}` ||
          combo.ids.join('') === `${sizeIds[i] + colorId}`
        ) {
          if (combo.quantity === 0) {
            //set first id of combo.ids to disabled
            setDisabled(combo.ids);
          } else {
            console.log('max', combo.quantity);
          }
        }
      });
    }
  };

and the code for colors button and size buttons are:

  {product.variants.map(
          (opt) =>
            opt.type === 'color' && (
              <Selector
                key={opt.id}
                opt={opt}
                setter={setColorId}
                id={colorId}
                disabled={disabled}
                setTitle={setColorTitle}
                getAvailableCombinations={getAvailableCombinations}
              />
            )
        )}
        {product.variants.map(
          (opt) =>
            opt.type === 'size' && (
              <Selector
                key={opt.id}
                opt={opt}
                setter={setSizeId}
                id={sizeId}
                setTitle={setSizeTitle}
                disabled={disabled}
                product={product}
              />
            )
        )}

in selector componenet I have this function to check for matching disabled id with showing buttons:

  const verifyDisabled = (id) => {
    if (disabled.includes(id)) {
      return true;
    }
    return false;
  };

the data that I am must use is:

       {
   "variants":[
      {
         "id":"8c3e4648-bac1-4113-871a-c1437870699e",
         "position":0,
         "type":"color",
         "name":"Color",
         "values":[
            {
               "id":"fef0ee43-cc82-41ce-93e8-4545343d2894",
               "value":"#f20d0d",
               "label":"Red"
            },
            {
               "id":"af99b52c-1791-4b09-9ecd-98d213624863",
               "value":"#f9e03e",
               "label":"Yellow"
            }
         ]
      },
      {
         "id":"f602839b-f474-46cf-8355-19561eb2ff23",
         "position":1,
         "type":"size",
         "name":"Size",
         "values":[
            {
               "id":"152b5d9b-0e8a-4c7f-afd0-065532a7d15a",
               "value":"L",
               "label":"Large"
            },
            {
               "id":"0cc1397e-4da1-450c-9d9c-5957fe5402b9",
               "value":"S",
               "label":"Small"
            }
         ]
      }
   ],
   "combinations":[
      {
         "id":"4b277987-ed73-4209-9b4f-74bf91ba68de",
         "ids":[
            "fef0ee43-cc82-41ce-93e8-4545343d2894",
            "152b5d9b-0e8a-4c7f-afd0-065532a7d15a"
         ],
         "quantity":0,
         "code":0,
         "barcode":0,
         "sellPrice":2000
      },
      {
         "id":"2ac35866-8c48-44a5-869b-c615a445b13e",
         "ids":[
            "fef0ee43-cc82-41ce-93e8-4545343d2894",
            "0cc1397e-4da1-450c-9d9c-5957fe5402b9"
         ],
         "quantity":0,
         "code":0,
         "barcode":0,
         "sellPrice":2000
      },
      {
         "id":"9ef5b938-b1ac-45a9-bd70-215d3dd0be55",
         "ids":[
            "af99b52c-1791-4b09-9ecd-98d213624863",
            "152b5d9b-0e8a-4c7f-afd0-065532a7d15a"
         ],
         "quantity":0,
         "code":0,
         "barcode":0,
         "sellPrice":2000
      },
      {
         "id":"0b08996d-6161-42f2-93e3-828c25117997",
         "ids":[
            "af99b52c-1791-4b09-9ecd-98d213624863",
            "0cc1397e-4da1-450c-9d9c-5957fe5402b9"
         ],
         "quantity":0,
         "code":0,
         "barcode":0,
         "sellPrice":2000
      }
   ],
}


Solution 1:[1]

To get the available combinations, we could use the following:

  useEffect(() => {
    setDisabled([]);
    setCannotAdd(false);
    item &&
      item.combinations.map((opt) => {
        if (
          (opt.ids[0] === colorId && opt.ids[1] === sizeId) ||
          (opt.ids[0] === sizeId && opt.ids[1] === colorId)
        ) {
          if (opt.quantity === 0) {
            setDisabled([...disabled, opt.ids]);
            setCannotAdd(true);
            console.log('disabled from choose', opt.ids);
          } else {
            return null;
          }
        } else {
          return null;
        }
      });
  }, [colorId, sizeId, item]);

where Item is the selected item or selected product.

and to show the variants as buttons and disable them when there is no quantity available for selected combinations of two variants for example (red/large), we could do the following:

  // a function to loop through disabled list and if we a matching 
  id we return true value to disable that button
  const verifyDisabled = (id) => {
    for (let i = 0; i < disabled.length; i++) {
      if (disabled[i][i] === id) {
        console.log('disabled', id);
        return true;
      }
    }
  };

 <div>
      <h4 className="font-bold">{opt.name}</h4>
      <ul className="flex flex-row justify-evenly p-2 px-10 gap-3">
        {opt.values.map((val) => (
          <li key={val.id}>
            <button
              disabled={verifyDisabled(val.id)}
              style={{
                backgroundColor: opt.type === 'color' ? val.name : '',
                borderRadius: '50%',
                border: id === val.id ? '2px solid black' : '1px solid #C9C9C9',
                boxShadow: '0px 0px 5px #C9C9C9',
                alignContent: 'center',
                alignItems: 'center',
                justifyContent: 'center',
                width: '30px',
                height: '30px',
                opacity: verifyDisabled(val.id) ? 0.5 : 1,
                cursor: verifyDisabled(val.id) ? 'not-allowed' : 'pointer',
              }}
              key={val.id}
              type="button"
              onClick={() => {
                setter(val.id);
                setTitle(val.label);
                getAvailableCombinations();
              }}
            >
              {opt.type === 'color' ? '' : val.name}
            </button>
          </li>
        ))}
      </ul>
    </div>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 saifaljanahi