How to use reduce to pass information to a base component? / Getting correct data passed with computed props in VueJS

Viewed 49

I'm currently working on an inventorying app and I am trying to display the boxID and the amount of items inside of that box on a baseCard component that I have made.

The computed property that I made boxCards needs to spit the data out in this format [{title: '', amount: null}] so it can be pushed onto each baseCard element.

Presently my computed property is giving me the title, but I cannot figure out how to get the amount of items inside of each box.

boxesInLocation returns this array: ["", "Box 1", "Box 4", "Box 4"]

Which is great, but now I need to count how many times each box shows up in that area and then push it to the reshapedItems function in the amount: spot.

Is this just a simple reduce method that I need to use? Because I've only be able to actually produce a number when calculating the length of the array.

Also, just reducing the array won't spit out the number to each individual instance of reshapedItem

Any ideas on what I can do here?

Cheers!

App.Vue Data:

data(){
    userData: {
        items: [
          {
            itemName: 'test book',
            category: 'Books',
            box: 'Box 3',
            location: 'Kitchen',
          },
          {
            itemName: 'test book 2',
            category: 'Books',
            box: 'Box 3',
            location: 'Kitchen',
          },
          {
            itemName: 'test book 3',
            category: 'Books',
            box: '',
            location: 'Basement',
          },
          {
            itemName: 'test record',
            category: 'Records',
            box: 'Box 1',
            location: 'Basement',
          },
          {
            itemName: 'test record 2',
            category: 'Records',
            box: 'Box 4',
            location: 'Basement',
          },
          {
            itemName: 'test furniture',
            category: 'Furniture',
            box: 'Box 2',
            location: 'Garage',
          },
          {
            itemName: 'test movie 1',
            category: 'Movies',
            box: 'Box 2',
            location: 'Garage',
          },
          {
            itemName: 'test movie 2',
            category: 'Movies',
            box: 'Box 2',
            location: 'Garage',
          },
          {
            itemName: 'test movie 3',
            category: 'Movies',
            box: 'Box 2',
            location: 'Garage',
          },
          {
            itemName: 'test Comicbook',
            category: 'Movies',
            box: 'Box 4',
            location: 'Basement',
          },
        ],
        boxes: [
          { name: 'Box 1', location: 'Basement' },
          { name: 'Box 2', location: 'Garage' },
          { name: 'Box 3', location: 'Kitchen' },
          { name: 'Box 4', location: 'Basement' },
        ],
   }

Page Component

  data() {
    return {
      items: this.userData.items,
      boxes: this.userData.boxes,
    }
  },
  computed: {
    boxCards() {
      const filteredItems = this.items.filter((item) => item.location === 'Basement')
      const itemsInBoxes = filteredItems.map((filteredItem) => {
        return filteredItem.box
      })

      const filteredBoxes = this.boxes.filter((box) => box.location === 'Basement')

      const reshapedBoxes = filteredBoxes.map((filteredBox) => {
        return { boxID: `${filteredBox.name}`, amount: 100 }
      })
      return reshapedBoxes
    },
2 Answers

You can count the items in the this.items array that have the same box name as the box in question:

return this.boxes
  .filter((box) => box.location === 'Basement')
  .map((box) => ({
    boxId: `${box.name}`,
    amount: this.items.filter(item => item.box === box.name).length
  }));

You need to save the number of occurrences of each box in a Map, then, get the amount of each one in the second loop you're doing:

const userData = {
  items: [
    { itemName: 'test book', category: 'Books', box: 'Box 3', location: 'Kitchen' },
    { itemName: 'test book 2', category: 'Books', box: 'Box 3', location: 'Kitchen' },
    { itemName: 'test book 3', category: 'Books', box: '', location: 'Basement' },
    { itemName: 'test record', category: 'Records', box: 'Box 1', location: 'Basement' },
    { itemName: 'test record 2', category: 'Records', box: 'Box 4', location: 'Basement' },
    { itemName: 'test furniture', category: 'Furniture', box: 'Box 2', location: 'Garage' },
    { itemName: 'test movie 1', category: 'Movies', box: 'Box 2', location: 'Garage' },
    { itemName: 'test movie 2', category: 'Movies', box: 'Box 2', location: 'Garage' },
    { itemName: 'test movie 3', category: 'Movies', box: 'Box 2', location: 'Garage' },
    { itemName: 'test Comicbook', category: 'Movies', box: 'Box 4', location: 'Basement' },
  ],
  boxes: [
    { name: 'Box 1', location: 'Basement' },
    { name: 'Box 2', location: 'Garage' },
    { name: 'Box 3', location: 'Kitchen' },
    { name: 'Box 4', location: 'Basement' },
  ]
};

function boxCards() {
  const boxesCount = userData.items
    .reduce((quantity, {box}) => 
      quantity.set(box, 1 + (quantity.get(box) || 0))
    , new Map);
  return userData.boxes
    .filter(box => 
      box.location === 'Basement'
    )
    .map(filteredBox => 
      ({ boxID: filteredBox.name, amount: boxesCount.get(filteredBox.name) })
    );
}

console.log( boxCards() );

Related