How to Filter Quantity By Attribute in ReactJs

I’m attempting to create a quantity filter based on color, size, or both. When I click the red color, for example, it displays the whole quantity of the red color, but if I press color red and size small, it displays the exact quantity I require. Is there a way to accomplish this?

This is what I mean.

enter image description here

When I select a color or a size, the quantity should be displayed. Also, there should not be a duplication of my error, since there are three red colors listed above the image.

Code


import React, { useState } from "react";

export default function ControlledRadios() {
  const [qty, setQty] = useState(0);

  const data = [
    {
      id: 1,
      name: "Product A",
      attributes: [
        {
          id: 1,
          color: "Red",
          size: "Small",
          qty: 200,
        },
        {
          id: 2,      
          color: "Red",
          size: "Medium",
          qty: 100,
        },
        {
          id: 3,
          color: "Red",
          size: "Large",
          qty: 300,
        },
        {
          id: 4,
          color: "Yellow",
          size: "Small",
          qty: 200,
        },
        {
          id: 5,
          color: "Yellow",
          size: "Medium",
          qty: 100,
        },
        {
          id: 6,
          color: "Yellow",
          size: "Large",
          qty: 300,
        },
      ],
    },
  ];

  const handleChange = (event) => {
    setQty(event.target.value);
  };

  return (
    <>
      <h1>Quantity: {qty}</h1>
      <fieldset value={qty} onChange={(event) => handleChange(event)}>
        <h3>Color:</h3>
        {data?.map(({ attributes }) => {
          return attributes.map(({ id, ...rest }) => (
            <>
              <label key={id}>
                <input
                  type="radio"
                  name="schedule-weekly-option"
                  value={rest.qty}
                />
                {rest.color}
              </label>
              <br />
            </>
          ));
        })}
        <h3>Size:</h3>
        {data?.map(({ attributes }) => {
          return attributes.map(({ id, ...rest }) => (
            <>
              <label key={id}>
                <input
                  type="radio"
                  name="schedule-weekly-option"
                  value={rest.qty}
                />
                {rest.size}
              </label>
              <br />
            </>
          ));
        })}
      </fieldset>
    </>
  );
}

As seen in the data value, I have multiple color and sizes goes something like this for example {color: "Red", Size: "Small", qty: 200} I have multiple red values, so right every red should be added so when I click the Red radio button it should display the quantity 600 because the quantity of all the red will be added. but if I press like color Red and size Small it should display 200.

PS: If possible can u not make duplicate of colors like I did 3 color red and yellow, to make it only 1 Red and 1 Yellow same goes with the size.

If you need anymore clarification you need or explanation please comment down below. Thanks

Answer

Phew! This should do the trick. The idea is to pass more data to your handleChange handleChange – see how I changed it? I grab the data straight out of the target element, which is not ideal, but works.

I didn’t do the filtering for you, good luck with that 🙂 Should be just adding a (granted, a fairly complex) .filter(...) to your .map(...).

document.onreadystatechange = () => {
  const {useState} = React;

  function ControlledRadios() {
    const [qty, setQty] = useState(0);

    const data = [
      {
        id: 1,
        name: "Product A",
        attributes: [
          {
            id: 1,
            color: "Red",
            size: "Small",
            qty: 200,
          },
          {
            id: 2,      
            color: "Red",
            size: "Medium",
            qty: 100,
          },
          {
            id: 3,
            color: "Red",
            size: "Large",
            qty: 300,
          },
          {
            id: 4,
            color: "Yellow",
            size: "Small",
            qty: 200,
          },
          {
            id: 5,
            color: "Yellow",
            size: "Medium",
            qty: 100,
          },
          {
            id: 6,
            color: "Yellow",
            size: "Large",
            qty: 999,
          },
        ],
      },
    ];

    const handleChange = (event) => {
      const id = event.target.value;
      const targetAttribute = data[0].attributes.find(x => x.id == id);
      if (event.target.name === "schedule-weekly-option-color") {
        let sum = 0;
        data[0].attributes.forEach((a) => {
            if (a.color===targetAttribute.color) {
              sum += a.qty;
            }
        });
        setQty(sum);
      } else {
        let sum = 0;
        data[0].attributes.forEach((a) => {
            if (a.color===targetAttribute.color && a.size===targetAttribute.size) {
              sum += a.qty;
            }
        });
        setQty(sum);
      }
    };

    return (
      <React.Fragment>
        <h1>Quantity: {qty}</h1>
        <fieldset value={qty} onChange={(event) => handleChange(event)}>
          <h3>Color:</h3>
          {data.map(({ attributes }) => {
            return attributes.map(a => (
                <label key={a.id}>
                  <input
                    type="radio"
                    name="schedule-weekly-option-color"
                    value={a.id}
                  />
                  {a.color}
                </label>
            ));
          })}
          <h3>Size:</h3>
          {data.map(item => {
            return item.attributes.map(a => (
                <label key={a.id}>
                  <input
                    type="radio"
                    name="schedule-weekly-option-size"
                    value={a.id}
                  />
                  {a.size}
                </label>
            ));
          })}
        </fieldset>
      </React.Fragment>
    );
  }

  ReactDOM.render(<ControlledRadios />, document.body);
};
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>