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>
)
}
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>;
};
Related
I am saving few data as an object in array in my local storage using AsyncStorage, I am able to do it in following way:
const [saveData, setSaveData] = useState([]);
useEffect(() => {
AsyncStorage.setItem('test4', JSON.stringify(saveData))
.then(json => console.log('success!'))
.catch(error => console.log('error!'));
}, [saveData]);
const _submitWithWeather = async text => {
let date = new Date();
const curDate = moment(date).format('MMM DD');
let newItem;
newItem = {
id: curDate,
date: curDate,
description: text,
imageURL: photo,
location: getLocation,
temperature: getWeather,
weatherType: geType,
};
setSaveData(prevList => {
prevList = prevList || [];
if (prevList.length < 0) {
return newItem;
} else {
return [...prevList, newItem];
}
});
};
<TouchableOpacity
onPress={() => {
_submitWithWeather(text);
}}>
<Text>save</Text>
</TouchableOpacity>
I am passing today's date as an id, because if the date on which I am saving my data, matches an object with same date then it should replace the object from array whose date is also today's data.
for example:
[
{
"date": "Jan 02",
"description": "1",
"id": "Jan 02",
"imageURL": "urlImage.jpg",
"location": "location",
"temperature": "13°C",
"weatherType": "Clear"
}
]
today's date is jan 02, and if I change the description or image and then click save , then this new object should replace the older object whose date is also jan 02
You can achieve this by using Array.filter to filter out based on your Id prop and spread operator to bring it back together.
const d1 = [
{
date: 'Jan 01',
description: '1',
},
{
date: 'Jan 02',
description: '2',
},
];
const d2 = {
date: 'Jan 01',
description: 'abc',
};
const getData = () => {
const d1WithoutDateToUpdate = d1.filter((d) => d.date != d2.date);
const updatedD1 = [...d1WithoutDateToUpdate, d2];
return updatedD1;
};
You could do a simple Array#map to update the data.
setSaveData(prevList => {
if (prevList.length) {
return prevList.map(obj => (newItem.date === obj.date) ? newItem : obj);
}
return [newItem]
});
As you've already initialized the value you don't need to set prevList = prevList || []
I have the following data structure from the API, it comes in as an array of Data, each Data element is intervaled by 1 hour.
interface Data {
time_bucket: string // ISO8601 string
aggregated_value: number // 0 and up
}
My plan is to format this for it to work with d3 to plot as a barchart. The barchart has a selector for you to group data into week, day, month, and year. I decided to create a function called groupBy that works quite like lodash's groupBy. It groups data to specified groups you want. This is the function
export function groupBy<T, K extends keyof any> (list: T[], criteria: (item: T) => K): Record<K, T[]> {
return list.reduce<Record<K, T[]>>((prev, curr) => {
const group = criteria(curr)
// eslint-disable-next-line
if (!prev[group]) {
prev[group] = []
}
prev[group].push(curr)
return prev
// eslint-disable-next-line
}, {} as Record<K, T[]>)
}
The problem is that the x scale of the graph is constructed in YYYY-MM-DD format. I wanted to group the data into each day while keeping the date format to YYYY-MM-DD. What I get right now from running the function looks like this in the snippets.
const data = [
{
time_bucket: '2021-06-01T16:00:00.000Z',
aggregated_value: 20
},
{
time_bucket: '2021-06-01T18:00:00.000Z',
aggregated_value: 20
},
{
time_bucket: '2021-06-02T16:00:00.000Z',
aggregated_value: 40
},
{
time_bucket: '2021-06-02T20:00:00.000Z',
aggregated_value: 40
},
{
time_bucket: '2021-06-03T05:00:00.000Z',
aggregated_value: 60
}
]
function groupBy(list, criteria) {
return list.reduce((prev, curr) => {
const group = criteria(curr)
if (!prev[group]) {
prev[group] = []
}
prev[group].push(curr)
return prev
}, {})
}
console.log(groupBy(data, (item) => dayjs.utc(item.time_bucket).get('date')))
<script src="https://unpkg.com/dayjs#1.8.21/dayjs.min.js"></script>
<script src="https://unpkg.com/dayjs#1.8.21/plugin/utc.js"></script>
<script>dayjs.extend(window.dayjs_plugin_utc)</script>
You can see that the output looks like this:
{
"1": [
{
"time_bucket": "2021-06-01T16:00:00.000Z",
"aggregated_value": 20
},
{
"time_bucket": "2021-06-01T18:00:00.000Z",
"aggregated_value": 20
}
],
"2": [
{
"time_bucket": "2021-06-02T16:00:00.000Z",
"aggregated_value": 40
},
{
"time_bucket": "2021-06-02T20:00:00.000Z",
"aggregated_value": 40
}
],
"3": [
{
"time_bucket": "2021-06-03T05:00:00.000Z",
"aggregated_value": 60
}
]
}
This is what I wanted
{
"2021-06-01": [
{
"time_bucket": "2021-06-01T16:00:00.000Z",
"aggregated_value": 20
},
{
"time_bucket": "2021-06-01T18:00:00.000Z",
"aggregated_value": 20
}
],
"2021-06-02": [
{
"time_bucket": "2021-06-02T16:00:00.000Z",
"aggregated_value": 40
},
{
"time_bucket": "2021-06-02T20:00:00.000Z",
"aggregated_value": 40
}
],
"2021-06-03": [
{
"time_bucket": "2021-06-03T05:00:00.000Z",
"aggregated_value": 60
}
]
}
What I wanted from the function is to be able to group the data into specified range, while still keeping the format of the date in YYYY-MM-DD format for me to still map it to the d3 x scale that I have generated. Is there any function in dayjs that could do this or is there any workaround. Thank you very much for the response.
After quite a while of research. I decided to round any date to the start of each time range.
I would be using it like this in the example.
const data = [
{
time_bucket: '2021-06-01T16:00:00.000Z',
aggregated_value: 20
},
{
time_bucket: '2021-06-01T18:00:00.000Z',
aggregated_value: 20
},
{
time_bucket: '2021-06-02T16:00:00.000Z',
aggregated_value: 40
},
{
time_bucket: '2021-06-02T20:00:00.000Z',
aggregated_value: 40
},
{
time_bucket: '2021-06-03T05:00:00.000Z',
aggregated_value: 60
}
]
function groupBy(list, criteria) {
return list.reduce((prev, curr) => {
const group = criteria(curr)
if (!prev[group]) {
prev[group] = []
}
prev[group].push(curr)
return prev
}, {})
}
console.log(groupBy(data, (item) => dayjs.utc(item.time_bucket).startOf('day').format('YYYY-MM-DD')))
<script src="https://unpkg.com/dayjs#1.8.21/dayjs.min.js"></script>
<script src="https://unpkg.com/dayjs#1.8.21/plugin/utc.js"></script>
<script>dayjs.extend(window.dayjs_plugin_utc)</script>
This way I can use the .format() that got exposed from startOf() to group the data into each time range.
I have a json object which is generated using lowdb. Each json entry has a timestamp. I wan't to get all the entry for yesterday, and today based on the timestamp.
The items variable here is just a json object. Here is a sample
{
"items": [
{
"date": 1596131220030,
"item": {
"price": "160,00",
"title": "Cotton Quarter-Zip Sweater"
}
},
{
"date": 1596232321030,
"item": {
"price": "160,00",
"title": "Cotton Quarter-Zip Sweater"
}
}
]
}
I want to get the items from yesterday, and today in this functuin
export async function report(){
try {
const items = db.get('items').value();
return items;
} catch (error) {
console.log(error);
}
}
You can compare with time values for the start of "today" and "yesterday", e.g.
// Return time value for the start of given date, default is today
function getToday(d = new Date()) {
return new Date(+d).setHours(0,0,0,0);
}
// Return time value for the start of day prior to given day, default is today
function getYesterday(d = new Date()) {
let e = new Date(getToday(d));
return e.setDate(e.getDate() - 1);
}
let data = {
"items": [
{"date": 1596085802005, // 30 Jul 2020
"item": "1"
},
{"date": 1596131220030, // 31 Jul 2020
"item": "2"
},
{"date": 1596232321030, // 1 Aug 2020
"item": "3"
}
]
}
// Run as for 1 Aug 2020
let yesterday = getYesterday(new Date(2020,7,1));
let result = data.items.filter(item => item.date >= yesterday);
console.log(result);
Results may vary based on the host timezone offset as the above uses local date values.
You need to parse the date, and compare the difference as follows:
let obj = {
"items": [
{
"date": 1596131220030,
"item": {
"price": "160,00",
"title": "Cotton Quarter-Zip Sweater"
}
},
{
"date": 1596232321030,
"item": {
"price": "160,00",
"title": "Cotton Quarter-Zip Sweater"
}
}
]
};
let list = [];
let items = obj.items;
let today = new Date();
for(let i = 0; i < items.length; i++){
var d = new Date(items[i].date);
var diff = Math.floor((d - today) / (1000 * 60 * 60 * 24));
if(diff == 0 || diff == -1)
list.push(items[i].item);
}
console.log(list);
I am facing an issue in React JS. I want to do compare or match the start_date with header date
Rest API
[
{
"id": "1",
"staff_name": "Jill",
"custom_service_name": "Jone",
"start_date": "2020-05-06 11:30:00",
"end_date": "2020-05-06 11:45:00",
},
{
"id": "2",
"staff_name": "james",
"custom_service_name": "smith",
"start_date": "2020-05-06 11:00:00",
"end_date": "2020-05-06 11:15:00",
}
]
console.log data:
1:00 AM //start_date
["9:43:36 AM", "9:13:36 AM", "10:13:36 AM"] //header_date
12:00 PM
["9:43:36 AM", "9:13:36 AM", "10:13:36 AM"] //header_date
2:15 AM
["9:43:36 AM", "9:13:36 AM", "10:13:36 AM"] //header_date
My Code:
var currentdate = new Date(); //header_date logic
var prevdate = new Date();
var firstdate = new Date();
prevdate.setTime(currentdate.getTime() - (30 * 60 * 1000));
firstdate.setTime(currentdate.getTime() + (30 * 60 * 1000));
var current = currentdate.toLocaleTimeString();
var previous = prevdate.toLocaleTimeString();
var first = firstdate.toLocaleTimeString();
var headerdate = [previous ,current, first];
this.state = {
headerdate:headerdate,
appointmentdata:[]
}
componentDidMount() { //get start_date
axios.get(`http://localhost/route/v1/appointment`)
.then(res => {
const appointmentdata = res.data;
console.log(appointmentdata);
this.setState({ appointmentdata });
})
}
I try , but this logic is not working
render() { return (
<div>
{this.state.appointmentdata.map(data =>
{ const dateTime = moment(data.start_date.toString());
if (dateTime.format("h:mm A") === this.state.headerdate)
{
return <p>{dateTime.format("h:mm A")}</p>; } //return the match date
else { return null; } })}
Demo:
https://codesandbox.io/s/quizzical-browser-9e3g4
What should i do?
Can anyone help me
I see you're using Moment. So you can use isSame built-in helper from them to achieve this.
Docs: https://momentjs.com/docs/#/query/is-same/
Example code:
const isSameDate = (start_date, header_date) => {
const startDate = moment(start_date);
const headerDate = moment(header_date);
return startDate.isSame(headerDate, 'day');
}
One small tip, you should move the date checking outside the render method, that would makes your code easier to read and maintainable
i have the following two array objects
const plan = [
{Item_ID : 01, Date:"2020-04-01", Items:"10"},
{Item_ID : 02, Date:"2020-04-01", Items:"20"},
{Item_ID : 03, Date:"2020-04-02", Items:"40"},
{Item_ID : 05, Date:"2020-04-03", Items:"10"},
];
const actual = [{Date:"2020-04-01", Actual_Items:"15"},
{Date:"2020-04-02", Actual_Items:"40"},
{Date:"2020-04-05", Actual_Items:"50"},
];
these two array shows planned sales and actual sales, based on these two array im trying to create the below array
const plan = [
{Item_ID : 01, Date:"2020-04-01", Items:"10", Actual_Items:"15"},
{Item_ID : 02, Date:"2020-04-01", Items:"20", Actual_Items:"15"},
{Item_ID : 03, Date:"2020-04-02", Items:"40", Actual_Items:"40"},
{Item_ID : 05, Date:"2020-04-03", Items:"10", Actual_Items:"0"},
{Item_ID : null, Date:"2020-04-04", Items:"0", Actual_Items:"0"},
{Item_ID : null, Date:"2020-04-05", Items:"0", Actual_Items:"50"},
];
so based on the planned array if these is actual sales done for that day we show otherwise show 0.
if nothing was planned but sales was done then Item_ID will be null Items will be null but Actual_Items need to show the number of sales.
I've created bellow map function maybe completely wrong logic and i was not able to continue future, any idea how to create this final array
let op = plan.map((e,i)=>{
let temp = actual.find(element=> element.Date === e.Date)
if(temp.Actual_Items) {
e.Actual_Items= temp.Actual_Items;
}
return e;
})
console.log(op);
You can join your two array like this:
let op = plan.concat(actual);
or
let op = [...plan, ...actual];
But before you might want to iterate over "actual" to modify the values "Item_ID" and "Items".
Solution look like:
const plan = [
{Item_ID : 01, Date:"2020-04-01", Items:"10"},
{Item_ID : 02, Date:"2020-04-01", Items:"20"},
{Item_ID : 03, Date:"2020-04-02", Items:"40"},
{Item_ID : 05, Date:"2020-04-03", Items:"10"},
];
const actual = [{Date:"2020-04-01", Actual_Items:"15"},
{Date:"2020-04-02", Actual_Items:"40"},
{Date:"2020-04-05", Actual_Items:"50"},
];
actual.forEach(function(part, index) {
part.Items = "0";
part.Item_ID = null;
this[index] = part;
}, actual);
let op = plan.concat(actual);
console.log(op);
You could use an object for same date, collect the plan values and then add actual as well.
You may finally add missing dates to the result array.
const
plan = [{ Item_ID: "01", Date: "2020-04-01", Items: "10" }, { Item_ID: "02", Date: "2020-04-01", Items: "20" }, { Item_ID: "03", Date: "2020-04-02", Items: "40" }, { Item_ID: "05", Date: "2020-04-03", Items: "10" }],
actual = [{ Date: "2020-04-01", Actual_Items: "15" }, { Date: "2020-04-02", Actual_Items: "40" }, { Date: "2020-04-05", Actual_Items: "50" }],
pattern = { Item_ID: null, Date: null, Items: "0", Actual_Items: "0" },
result = Object
.values(actual.reduce(
(r, o) => {
r[o.Date] = r[o.Date] || [{ ...pattern }];
r[o.Date].forEach(p => Object.assign(p, o));
return r;
},
plan.reduce((r, o) => {
(r[o.Date] = r[o.Date] || []).push({ ...pattern, ...o });
return r;
}, {})
))
.flat()
.reduce((r, o, i, { [i - 1]: prev }) => {
if (!r) return [o];
var p = new Date(prev.Date).getTime() + 1000 * 60 * 60 * 24;
while (p < new Date(o.Date).getTime()) {
let d = new Date;
d.setTime(p);
r.push({ ...pattern, Date: d.toISOString().slice(0, 10) });
p += 1000 * 60 * 60 * 24;
}
r.push(o);
return r;
}, undefined);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }