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.