0

I'm building off a prior question: React displaying data in a table with dynamic columns

In that question I was working on building a table to reflect the amount of hours worked for a client per day in a month (selected by the user, but the codesandbox I made is simplified). For another part of the app, I'm expanding that table so that an admin selects a user, month, and year and then the table populates the days of the month as the header, with each row being a different client. After a few steps, I have the output close to what I'm looking for, but 1 step shy and I'm stuck...

Heres the simplified data set and current logic:

const data = [
    {
    start: "2022-04-3",
    hours: 1,
    client: {
        id: "123",
      fullName: "Tom Tom"
    }
  },
  {
    start: "2022-04-10",
    hours: 2,
    client: {
        id: "123",
      fullName: "Tom Tom"
    }
  },
  {
    start: "2022-04-10",
    hours: 3,
    client: {
        id: "123",
      fullName: "Tom Tom"
    }
  },
  {
    start: "2022-04-10",
    hours: 1,
    client: {
        id: "123",
      fullName: "Tom Tom"
    }
  },
  {
    start: "2022-04-13",
    hours: 1,
    client: {
        id: "456",
      fullName: "Jack Jack"
    }
  },
  {
    start: "2022-04-13",
    hours: 2,
    client: {
        id: "123",
      fullName: "Tom Tom"
    }
  },
  {
    start: "2022-04-15",
    hours: 1,
    client: {
        id: "789",
      fullName: "Pete Pete"
    }
  },
  {
    start: "2022-04-15",
    hours: 1,
    client: {
        id: "789",
      fullName: "Pete Pete"
    }
  }
]

let collData = data.reduce((accumulator, currentValue) => { 
    let existing = accumulator.find((n) => n.client.id === currentValue.client.id && n.start === currentValue.start);
            if (existing) {
              existing.hours += currentValue.hours;
            } else {
              accumulator.push(currentValue);
            }
            return accumulator;
          }, []);
        console.log("step 1 ", collData);
        
        
let res = {};



collData.forEach((item) => {
    const splitDate = item.start.split("-");
    const day = splitDate[splitDate.length - 1];

    const newStat = { start: parseInt(day), hours: item.hours};
      
   if(res[item.client.id])
   {
       let stats = res[item.client.id].stats;
        stats = [...stats, newStat];
        res[item.client.id].stats = stats;
   }
   else{
      res[item.client.id] = {
        client: item.client,
        stats: [newStat]
      }
   }
    
  });


  let filtArr = [];
  
  const daysInMonth = 30;
 
    let dayInfo = [];
    for (let i = 1; i <= daysInMonth; i++) {
      dayInfo.push(i)
 
      // create an array and fill hours with 0
 var dayArr = dayInfo.map((day) => ({
        day: day,
        hours: 0
      }));
      } 
      
const displayDates = (id) => {
  const client = res[id];

    let temp = [];
      dayArr.map((i, idx) => {
        const getHours = client.stats.find((item) => item.start === i.day);
        let newStats = {};
        if (getHours) {
          newStats = {
          
            client: {fullName: client.client.fullName, id: client.client.id},
            stats: [{
                day: i.day,
                hours: getHours.hours,
            }]
            
            
          };
      
        }
        else{
          newStats = {
            
            client: {fullName: client.client.fullName, id: client.client.id},
            stats: [{
                day: i.day,
            hours: 0,
            
            }]
            
          };
        }
        temp[idx] = newStats;
      });
 return temp;
      
}

 Object.keys(res).forEach(id=>{
    filtArr = [...filtArr, res[id]];
        console.log(displayDates(id))
  })

In order to map out the table rows/data, I'm trying to get the final data to be structured as: (currently client is being populated with each day of the month/hours)

current output = 
[{
  client: {
    fullName: "Pete Pete",
    id: "789"
 },
  stats: [{
    day: 1,
    hours: 0
   }]
 }, {
  client: {
    fullName: "Pete Pete",
    id: "789"
 },
  stats: [{
    day: 2,
    hours: 0
  }]
 }, {
  client: {
    fullName: "Pete Pete",
    id: "789"
 },
  stats: [{
    day: 3,
    hours: 0
  }]
 },//and so on for all days of the month
]

ideal output=
[
  {
    client: {name: "name name", id: "123"},
    stats: [
             {day: 1, hours: 0},
             {day: 2, hours: 1},
             {day: 3, hours: 0},
             {day: 4, hours: 2},
             //and so on for all the days in the month
            ]
  }
]

I've tried using map and forEach to get this structure, but I must not be understanding something about accessing the object properties in the array (I keep getting undefined errors). I figured there was probably somewhere in the logic along the way I could have structure it like this, but I'm not skilled enough to figure that out. I have a JSFiddle with a live example: https://jsfiddle.net/joznox/xzd5y142/3/

Any help would be greatly appreciated.

1 Answer 1

0

I got some help off this site and they gave me a much cleaner working structure. In the end, it is a total rework of the patched together pieces I had put together before, but makes for a much more elegant solution. For anyone who comes along, here is the complete example:

 const data = [{
            start: "2022-04-3",
            hours: 1,
            client: {
                id: "123",
                fullName: "Tom Tom"
            }
        },
        {
            start: "2022-04-10",
            hours: 2,
            client: {
                id: "123",
                fullName: "Tom Tom"
            }
        },
        {
            start: "2022-04-10",
            hours: 3,
            client: {
                id: "123",
                fullName: "Tom Tom"
            }
        },
        {
            start: "2022-04-3",
            hours: 3,
            client: {
                id: "123",
                fullName: "Tom Tom"
            }
        },
        {
            start: "2022-04-10",
            hours: 1,
            client: {
                id: "123",
                fullName: "Tom Tom"
            }
        },
        {
            start: "2022-04-13",
            hours: 1,
            client: {
                id: "456",
                fullName: "Jack Jack"
            }
        },
        {
            start: "2022-04-13",
            hours: 2,
            client: {
                id: "123",
                fullName: "Tom Tom"
            }
        },
        {
            start: "2022-04-15",
            hours: 1,
            client: {
                id: "789",
                fullName: "Pete Pete"
            }
        },
        {
            start: "2022-04-15",
            hours: 1,
            client: {
                id: "789",
                fullName: "Pete Pete"
            }
        }
    ]


var finalResult = (function (data, month, year) {
    
    let finalObject = {};
    var dateSet = [];
  
 
  
  const dataArr = data

    
    //Mapping the data set to something more manageable
    dataArr.forEach(x => {
        let clientObject = finalObject[x.client.id];

        if (!clientObject) {
            finalObject[x.client.id] = {
                clientName: x.client.fullName,
                id: x.client.id,
                stats: {}
            };
            clientObject = finalObject[x.client.id];
        }
        let currentDate = clientObject.stats[x.start];
        if (!currentDate) {
            clientObject.stats[x.start] = {};
        }
        
        clientObject.stats[x.start] = {
            start: x.client.start,
            hours: !currentDate?x.hours:currentDate.hours+x.hours
        };
    });

    //preparing the date sets
    for (var i = 1; i < 30; i++) {
        dateSet.push(year + '-' + (month<9?"0"+month:month) + '-' + i);
    }

    // Composing the final data set
    Object.keys(finalObject).map(key=>{
        let currentClient = finalObject[key];
        let newStats = [];

        dateSet.forEach(date=>{
            var dateObject = currentClient.stats[date];
            newStats.push({
                start:date,
                hours:!dateObject?0:dateObject.hours
            });
        });
        
        currentClient.stats= newStats;
    });

    //console.log(Object.values(finalObject));
  return Object.values(finalObject)
 
})(data, 4, 2022)

console.log(finalResult)

which makes the output as follows, and sets it up to be easily mapped to table rows:

[{
  clientName: "Tom Tom",
  id: "123",
  stats: [{
  hours: 0,
  start: "2022-04-1"
}, {
  hours: 0,
  start: "2022-04-2"
}, {
  hours: 4,
  start: "2022-04-3"
}, {
  hours: 0,
  start: "2022-04-4"
}, {
  hours: 0,
  start: "2022-04-5"
}, {
  hours: 0,
  start: "2022-04-6"
}, {
  hours: 0,
  start: "2022-04-7"
}, {
  hours: 0,
  start: "2022-04-8"
}, {
  hours: 0,
  start: "2022-04-9"
}, {
  hours: 6,
  start: "2022-04-10"
}, {
  hours: 0,
  start: "2022-04-11"
}, {
  hours: 0,
  start: "2022-04-12"
}, {
  hours: 2,
  start: "2022-04-13"
}, {
  hours: 0,
  start: "2022-04-14"
}, {
  hours: 0,
  start: "2022-04-15"
}, {
  hours: 0,
  start: "2022-04-16"
}, {
  hours: 0,
  start: "2022-04-17"
}, {
  hours: 0,
  start: "2022-04-18"
}, {
  hours: 0,
  start: "2022-04-19"
}, {
  hours: 0,
  start: "2022-04-20"
}, {
  hours: 0,
  start: "2022-04-21"
}, {
  hours: 0,
  start: "2022-04-22"
}, {
  hours: 0,
  start: "2022-04-23"
}, {
  hours: 0,
  start: "2022-04-24"
}, {
  hours: 0,
  start: "2022-04-25"
}, {
  hours: 0,
  start: "2022-04-26"
}, {
  hours: 0,
  start: "2022-04-27"
}, {
  hours: 0,
  start: "2022-04-28"
}, {
  hours: 0,
  start: "2022-04-29"
}]
}, {
  clientName: "Jack Jack",
  id: "456",
  stats: [{
  hours: 0,
  start: "2022-04-1"
}, {
  hours: 0,
  start: "2022-04-2"
}, {
  hours: 0,
  start: "2022-04-3"
}, {
  hours: 0,
  start: "2022-04-4"
}, {
  hours: 0,
  start: "2022-04-5"
}, {
  hours: 0,
  start: "2022-04-6"
}, {
  hours: 0,
  start: "2022-04-7"
}, {
  hours: 0,
  start: "2022-04-8"
}, {
  hours: 0,
  start: "2022-04-9"
}, {
  hours: 0,
  start: "2022-04-10"
}, {
  hours: 0,
  start: "2022-04-11"
}, {
  hours: 0,
  start: "2022-04-12"
}, {
  hours: 1,
  start: "2022-04-13"
}, {
  hours: 0,
  start: "2022-04-14"
}, {
  hours: 0,
  start: "2022-04-15"
}, {
  hours: 0,
  start: "2022-04-16"
}, {
  hours: 0,
  start: "2022-04-17"
}, {
  hours: 0,
  start: "2022-04-18"
}, {
  hours: 0,
  start: "2022-04-19"
}, {
  hours: 0,
  start: "2022-04-20"
}, {
  hours: 0,
  start: "2022-04-21"
}, {
  hours: 0,
  start: "2022-04-22"
}, {
  hours: 0,
  start: "2022-04-23"
}, {
  hours: 0,
  start: "2022-04-24"
}, {
  hours: 0,
  start: "2022-04-25"
}, {
  hours: 0,
  start: "2022-04-26"
}, {
  hours: 0,
  start: "2022-04-27"
}, {
  hours: 0,
  start: "2022-04-28"
}, {
  hours: 0,
  start: "2022-04-29"
}]
}, {
  clientName: "Pete Pete",
  id: "789",
  stats: [{
  hours: 0,
  start: "2022-04-1"
}, {
  hours: 0,
  start: "2022-04-2"
}, {
  hours: 0,
  start: "2022-04-3"
}, {
  hours: 0,
  start: "2022-04-4"
}, {
  hours: 0,
  start: "2022-04-5"
}, {
  hours: 0,
  start: "2022-04-6"
}, {
  hours: 0,
  start: "2022-04-7"
}, {
  hours: 0,
  start: "2022-04-8"
}, {
  hours: 0,
  start: "2022-04-9"
}, {
  hours: 0,
  start: "2022-04-10"
}, {
  hours: 0,
  start: "2022-04-11"
}, {
  hours: 0,
  start: "2022-04-12"
}, {
  hours: 0,
  start: "2022-04-13"
}, {
  hours: 0,
  start: "2022-04-14"
}, {
  hours: 2,
  start: "2022-04-15"
}, {
  hours: 0,
  start: "2022-04-16"
}, {
  hours: 0,
  start: "2022-04-17"
}, {
  hours: 0,
  start: "2022-04-18"
}, {
  hours: 0,
  start: "2022-04-19"
}, {
  hours: 0,
  start: "2022-04-20"
}, {
  hours: 0,
  start: "2022-04-21"
}, {
  hours: 0,
  start: "2022-04-22"
}, {
  hours: 0,
  start: "2022-04-23"
}, {
  hours: 0,
  start: "2022-04-24"
}, {
  hours: 0,
  start: "2022-04-25"
}, {
  hours: 0,
  start: "2022-04-26"
}, {
  hours: 0,
  start: "2022-04-27"
}, {
  hours: 0,
  start: "2022-04-28"
}, {
  hours: 0,
  start: "2022-04-29"
}]
}]
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.