REACT- Displaying and filtering specific data

Viewed 291

I want to display by default only data where the status are Pending and Not started. For now, all data are displayed in my Table with these status: Good,Pending, Not started (see the picture).

But I also want to have the possibility to see the Good status either by creating next to the Apply button a toggle switch : Show good menus, ( I've made a function Toggle.jsx), which will offer the possibility to see all status included Good.

I really don't know how to do that, here what I have now :

  export default function MenuDisplay() {
      const { menuId } = useParams();
      const [selected, setSelected] = useState({});
      const [hidden, setHidden] = useState({});
      const [menus, setMenus] = useState([]);    
    
      useEffect(() => {
        axios.post(url,{menuId:parseInt(menuId)})
            .then(res => {
                console.log(res)
                setMenus(res.data.menus)
            })
            .catch(err => {
                console.log(err)
            })
    }, [menuId]);
    
      // If any row is selected, the button should be in the Apply state
      // else it should be in the Cancel state
      const buttonMode = Object.values(selected).some((isSelected) => isSelected)
        ? "apply"
        : "cancel";
    
      const rowSelectHandler = (id) => (checked) => {
        setSelected((selected) => ({
          ...selected,
          [id]: checked
        }));
      };
    
      const handleClick = () => {
        if (buttonMode === "apply") {
          // Hide currently selected items
          const currentlySelected = {};
          Object.entries(selected).forEach(([id, isSelected]) => {
            if (isSelected) {
              currentlySelected[id] = isSelected;
            }
          });
          setHidden({ ...hidden, ...currentlySelected });
    
          // Clear all selection
          const newSelected = {};
          Object.keys(selected).forEach((id) => {
            newSelected[id] = false;
          });
          setSelected(newSelected);
        } else {
          // Select all currently hidden items
          const currentlyHidden = {};
          Object.entries(hidden).forEach(([id, isHidden]) => {
            if (isHidden) {
              currentlyHidden[id] = isHidden;
            }
          });
          setSelected({ ...selected, ...currentlyHidden });
    
          // Clear all hidden items
          const newHidden = {};
          Object.keys(hidden).forEach((id) => {
            newHidden[id] = false;
          });
          setHidden(newHidden);
        }
      };
    
      const matchData = (
        menus.filter(({ _id }) => {
        return !hidden[_id];
      });
    
      const getRowProps = (row) => {
        return {
          style: {
            backgroundColor: selected[row.values.id] ? "lightgrey" : "white"
          }
        };
      };
    
      const data = [
        {
          Header: "id",
          accessor: (row) => row._id
        },
        {
          Header: "Name",
          accessor: (row) => (
            <Link to={{ pathname: `/menu/${menuId}/${row._id}` }}>{row.name}</Link>
          )
        },
        {
          Header: "Description",
          //check current row is in hidden rows or not
          accessor: (row) => row.description
        },
       {
          Header: "Status",
          accessor: (row) => row.status
       },
        {
          Header: "Dishes",
          //check current row is in hidden rows or not
          accessor: (row) => row.dishes,
          id: "dishes",
          Cell: ({ value }) => value && Object.values(value[0]).join(", ")
        },
        {
          Header: "Show",
          accessor: (row) => (
            <Toggle
              value={selected[row._id]}
              onChange={rowSelectHandler(row._id)}
            />
          )
        }
      ];
    
      const initialState = {
        sortBy: [
          { desc: false, id: "id" },
          { desc: false, id: "description" }
        ],
        hiddenColumns: ["dishes", "id"]
      };
    
      return (
        <div>
          <button type="button" onClick={handleClick}>
            {buttonMode === "cancel" ? "Cancel" : "Apply"}
          </button>
    
          <Table
            data={matchData}
            columns={data}
            initialState={initialState}
            withCellBorder
            withRowBorder
            withSorting
            withPagination
            rowProps={getRowProps}
          />
        </div>
      );
    }

Here my json from my api for menuId:1:

  [
      {
        "menuId": 1,
        "_id": "123ml66",
        "name": "Pea Soup",
        "description": "Creamy pea soup topped with melted cheese and sourdough croutons.",
        "dishes": [
          {
            "meat": "N/A",
            "vegetables": "pea"
          }
        ],
        "taste": "Good",
        "comments": "3/4",
        "price": "Low",
        "availability": 0,
        "trust": 1,
        "status": "Pending",
        "apply": 1
      },
     //...other data
    ]

Here my CodeSandbox

Here a picture to get the idea: enter image description here

1 Answers

Here's the second solution I proposed in the comment:

// Setting up toggle button state
const [showGood, setShowGood] = useState(false);
const [menus, setMenus] = useState([]);

  // Simulate fetch data from API
  useEffect(() => {
    async function fetchData() {
      // After fetching data with axios or fetch api
      // We process the data
      const goodMenus = dataFromAPI.filter((i) => i.taste === "Good");
      const restOfMenus = dataFromAPI.filter((i) => i.taste !== "Good");

      // Combine two arrays into one using spread operator
      // Put the good ones to the front of the array
      setMenus([...goodMenus, ...restOfMenus]); 
    }

    fetchData();
  }, []);

return (
  <div>
    // Create a checkbox (you can change it to a toggle button)
    <input type="checkbox" onChange={() => setShowGood(!showGood)} /> 

    // Conditionally pass in menu data based on the value of toggle button "showGood"
    <Table
      data={showGood ? menus : menus.filter((i) => i.taste !== "Good")}
    />
  </div>
);

On ternary operator and filter function:

showGood ? menus : menus.filter((i) => i.taste !== "Good")

If button is checked, then showGood's value is true, and all data is passed down to the table, but the good ones will be displayed first, since we have processed it right after the data is fetched, otherwise, the menus that doesn't have good status is shown to the UI.

See sandbox for the simple demo.

Related