1

I have an array of object as follows. The data is based on created_date for e.g. ("2021-09-12")

As you can see, i have got last 5 days of data. i.e. 12th Sep, 11th Sep, 10th Sep, 9th Sep and 8th Sep. The response does not have any data for 11th sept and 8th Sept.

const buildData = [
    {
      "project_id": "1H16SET9829",
      "created_date": "2021-09-12",
      "status": "P"
    },
    {
      "project_id": "1J01SET10974",
      "created_date": "2021-09-10",
      "status": "F"
    },
    {
      "project_id": "1J01SET10971",
      "created_date": "2021-09-09",
      "status": "P"
    },
    {
      "project_id": "1J01SET10969",
      "created_date": "2021-09-09",
      "status": "F"
    }
]

Based on this above information, i have to display data in UI using react functional component as follows

  Sep 12, 2021  | Sep 11,2021 |   Sep 10, 2021   |   Sep 09, 2021    | Sep 08, 2021
1H16SET9829 (P) |             | 1J01SET10974 (F) | 1J01SET10971 (P)  |
                |             |                  | 1J01SET10971 (F)  |

Can someone please let me know how to achieve this. I tried the following but it doesnot display the correct data. I am not getting how to display correct project_id below its date. Also some dates have 2 project_ids in it. for e.g. Sep 09,2021 has 2 project_ids and both need to be displayed one below the other and then proceed with next date.

const renderProjects = (props) => {
    const items = buildData.map( (t, idx) => (
        <>
          <div>{ t.created_date }</div>
          <div>{t.project_id</div>
        </>
    ))

    return (
        <div className="project-list">
            { items }
        </div>
    )
}
3
  • 2
    You probably want to first convert your data into an object where the keys are dates and the values are lists of project IDs. Then you can map it from there. I am working on a more complete answer. Commented Sep 13, 2021 at 23:10
  • @nullromo- thanks for the feedback. is it complicated to achieve ? can you share some online reference which achieves. i can try to understand and replicate it Commented Sep 13, 2021 at 23:35
  • 1
    I posted an answer. You can try that out and comment if there is any confusion or further questions. Commented Sep 13, 2021 at 23:43

1 Answer 1

1

You can do something like this (see inline comments):

const buildData = [
    {
        project_id: '1H16SET9829',
        created_date: '2021-09-12',
        status: 'P',
    },
    {
        project_id: '1J01SET10974',
        created_date: '2021-09-10',
        status: 'F',
    },
    {
        project_id: '1J01SET10971',
        created_date: '2021-09-09',
        status: 'P',
    },
    {
        project_id: '1J01SET10969',
        created_date: '2021-09-09',
        status: 'F',
    },
];

export const RenderProjects = (props) => {
    // convert the buildData into a map from date -> list of `{project_id, status}`s
    const buildDataByDate = buildData.reduce((map, project) => {
        const projectInfo = {
            project_id: project.project_id,
            status: project.status,
        };
        if (!map[project.created_date]) {
            map[project.created_date] = [projectInfo];
        } else {
            map[project.created_date].push(projectInfo);
        }
        return map;
    }, {});


    // find the first and last dates
    const minDate = Object.keys(buildDataByDate).sort()[0];
    const maxDate = Object.keys(buildDataByDate).sort().reverse()[0];
    // find how many days are between them
    const daysBetween =
        (Date.parse(maxDate) - Date.parse(minDate)) / (24 * 60 * 60 * 1000);
    // add in the missing dates
    [...Array(daysBetween).keys()].forEach((increment) => {
        const dateToAdd = new Date(
            Date.parse(minDate) + increment * 24 * 60 * 60 * 1000,
        )
            .toISOString()
            .substring(0, 10);
        if (!buildDataByDate[dateToAdd]) {
            buildDataByDate[dateToAdd] = [];
        }
    });

    // render something for each entry in that map
   const items = Object.entries(buildDataByDate)
        .sort((a, b) => {
            return Date.parse(b[0]) - Date.parse(a[0]);
        })
        .map(([date, projects]) => {
            return (
                <React.Fragment key={date}>
                    <div>{date}</div>
                    {projects.map((project) => {
                        return (
                            <div
                                key={project.project_id}
                            >{`${project.project_id} (${project.status})`}</div>
                        );
                    })}
                </React.Fragment>
            );
        });

    return <div className='project-list'>{items}</div>;
};
Sign up to request clarification or add additional context in comments.

9 Comments

I edited this answer accordingly, so you can see how to handle that.
Now you can see that the map is from date to {project_id, status} instead of just date to project id. Then as you are rendering each project, you can render the status as well as the id.
Oh, I see, so you want to have the date shown anyway, just with no entries under it.
I added another section of code on how to add in the missing dates between the min and max dates available. If you want to include other dates, you will have to modify how minDate and maxDate are defined. They could be passed in as props for example, or defined globally. Hopefully that helps.
Of course I ran the output. Sure, you can sort the entries when you render them, right after the call to Object.entries. I updated the answer. At this point I think this particular question can be considered answered and if there are more features to add it will be up to you. If you feel this answer is sufficient for the question at hand then you can mark it as accepted.
|

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.