I'm working on a calendar app, which has an Agenda from "react-native-calendars". To display dates it needs the following:
items={{'2012-05-22': [{name: 'item 1 - any js object'}], ...}}
In my firebase backend I'm storing the start and end day of an appointment and also an array, which includes every day of it (so if the appointment started yesterday and ends tomorrow, the array stores yesterday, today and tomorrow as dates. The amount of dates in the array varies!)
The api data structure is the following:
apiData = [
{data: {allDays: ["2021-08-18", "2021-08-19", "2021-08-20"],
start: "2021-08-18",
end: "2021-08-20"
},
id: "string"},
{data: {allDays: ["2021-08-20", "2021-08-21", "2021-08-22", "2021-08-23"],
start: "2021-08-20",
end: "2021-08-23"
},
id: "string"},
//more Data
]
I got the following code to map the documents:
let markedDayAll = {};
{apiData.map(({data: {start, end, allDays}}) => (
markedDayAll[alldays] = [{
start: start,
end: end
}]
))};
which outputs in the correct "items" format, but right now, obviously, it is displayed like this:
items={{
'2021-08-18, 2021-08-19, 2021-08-20': [{start: "2021-08-18, end: "2021-08-20}]
}}
But I need the following:
items={{
'2021-08-18': [{start: "2021-08-18, end: "2021-08-20}],
'2021-08-19': [{start: "2021-08-18, end: "2021-08-20}],
'2021-08-20': [{start: "2021-08-18, end: "2021-08-20}]
}}
How do I properly map the data, so I get the desired result?
You can use array#reduce to iterate through each object and then iterate through each date in allDays and generate your object.
const apiData = [ {data: {allDays: ["2021-08-18", "2021-08-19", "2021-08-20"], start: "2021-08-18", end: "2021-08-20" }, id: "string"}, {data: {allDays: ["2021-08-20", "2021-08-21", "2021-08-22", "2021-08-23"], start: "2021-08-20", end: "2021-08-23" }, id:"string"} ],
result = apiData.reduce((r, {data}) => {
data.allDays.forEach(date => {
r[date] ??= [];
r[date].push({start: data.start, end: data.end});
});
return r;
},{});
console.log(result);
Related
I am working with Vue, but this is a general javascript question.
I make a call to an api to get cat messages for a chat UI. The initial call returns an array of objects where each object is a chat message object as below.
data: [
0: {id: 1, created_at: "2022-05-20T15:12:40.000000Z", updated_at: "2022-05-20T17:18:03.000000Z",…}
1: {id: 2, created_at: "2022-05-20T15:12:41.000000Z", updated_at: "2022-05-20T17:18:04.000000Z",…}
2: {id: 3, created_at: "2022-05-20T15:12:41.000000Z", updated_at: "2022-05-20T17:18:04.000000Z",…}
3: {id: 4, created_at: "2022-05-20T15:12:41.000000Z", updated_at: "2022-05-20T17:18:04.000000Z",…}
]
I initial wanted to format the message so they can be grouped by their dates in the chat window. This is the code I used to group them
This is a computed property in vue
const formattedChats = computed(() => {
let dateFormattedMessages = messages.value.map(message => {
return {...message, updated_at: new Date(message.updated_at).toDateString(), created_at: new Date(message.created_at).toDateString()}
})
return dateFormattedMessages.reduce((total, currentValue) => {
total[currentValue.updated_at] = total[currentValue.updated_at] || [];
total[currentValue.updated_at].push(currentValue);
return total;
}, Object.create(null));
})
The above will first take the each chat object an convert their updated_at and created_at to a date string and then group the array using the updated_at.
The result was as follows:
formattedChats = {
Fri Jun 24 2022: [
{...}, {...
]
Fri May 20 2022:[
{...}, {...
]
Mon Jun 27 2022:Array[
{...}, {...
]
Sat May 21 2022:Array[
{...}, {...
]
Tue Jun 28 2022:Array[
{...}, {...
]
}
If you notice, the problem I am facing is that the dates are not arranged in any order. it doesnt make sense to render it to the UI like this because the resulting chats with not be arranged by date.
This is how the UI should look
You need to use arrays (or a map) to keep the order sorted. I would use an array of arrays. First you need to sort the data on date (I used updated_at, which I made of type Date in the data array). Then iterate over the sorted array. See snippet below.
const data = [{
id: 1,
updated_at: new Date("2022-05-21T15:12:40.000000Z"),
created_at: "2022-05-20T17:18:03.000000Z"
},
{
id: 2,
updated_at: new Date("2022-05-20T15:12:41.000000Z"),
created_at: "2022-05-20T17:18:04.000000Z"
},
{
id: 3,
updated_at: new Date("2022-05-23T15:12:41.000000Z"),
created_at: "2022-05-20T17:18:04.000000Z"
},
{
id: 4,
updated_at: new Date("2022-05-21T15:12:41.000000Z"),
created_at: "2022-05-20T17:18:04.000000Z"
},
]
const sortedData = data.sort(
(a, b) => Number(a.updated_at) - Number(b.updated_at),
);
let currentDay = sortedData[0].updated_at;
const stillCurrentDay = (dayOfMessage) => {
return dayOfMessage.getFullYear() === currentDay.getFullYear() &&
dayOfMessage.getMonth() === currentDay.getMonth() &&
dayOfMessage.getDate() === currentDay.getDate()
}
let dayMessageArray = [];
const fullMessageArray = [];
const createMessagesArray = (messages) => {
const newDay = {};
newDay[currentDay.toISOString().split('T')[0]] = messages;
fullMessageArray.push(newDay);
}
sortedData.forEach(message => {
if (!stillCurrentDay(message.updated_at)) {
createMessagesArray(dayMessageArray);
currentDay = message.updated_at;
dayMessageArray = [];
}
dayMessageArray.push(message);
});
createMessagesArray(dayMessageArray);
console.log(fullMessageArray);
Hope this helps. Perhaps there are easier ways, please let me know.
I have an Array of Objects like this:
[{
date: 2022-04-07T01:00:00.000+00:00,
type: 'profit'
amount: 200
},{
date: 2022-04-07T01:00:00.000+00:00,
type: 'withdraw'
amount: 600
},{
date: 2022-04-07T01:00:00.000+00:00,
type: 'invest'
amount: 900
},{
date: 2022-04-08T01:00:00.000+00:00,
type: 'deposit'
amount: 200
},{
date: 2022-04-08T01:00:00.000+00:00,
type: 'profit'
amount: 200
}]
In the datasource the dates are not in order so I am sorting by date like this:
this.allTransactions.sort((a: any, b: any) => {
return new Date(b.date).getTime() - new Date(a.date).getTime();
});
However I need to also sort any objects with the same date by an external array:
['invest', 'withdraw', 'profit']
I'm struggling with the second part sorting the date groups already sorted by the order in the array. this.allTransactions is in an *ngFor loop in Angular 12
You can add an extra condition after your current one, which will be used if the first one resolves as 0
const typeOrder = ['invest', 'withdraw', 'profit']
transactions.sort((a, b) => {
return new Date(b.date).getTime() - new Date(a.date).getTime() || typeOrder.indexOf(a.type) - typeOrder.indexOf(b.type)
});
I am working with the object like this:-
{
0:
buyAmount: 16.664328043964396
buyAmountInUsd: 16.685266204095775
date: {date: '2021-12-07'}
sellAmount: {USD: 500, INR: 35000}
1:
buyAmount: 1004.7015442959262
buyAmountInUsd: 1005.9639175379324
date: {date: '2021-12-07'}
sellAmount: {USD: 1000, INR: 79000}
......
and I am trying to make a new array using useState hook with this data but the problem I am facing is how to filter data and make an almost similar array with the same data.
e.g.:-
0: [amount: 500, date: '2021-12-07'],
1: [amount: 1000, date: '2021-12-07']
The problem I am facing is I don't know the approach how to get the data like amount = sellAmount.USD and date = date.date
I thought of trying the for...of But I don't think it will be a good hit.
You can do this with Array.map
const arr = [{
buyAmount: 16.664328043964396,
buyAmountInUsd: 16.685266204095775,
date: {date: '2021-12-07'},
sellAmount: {USD: 500, INR: 35000}
},{
buyAmount: 1004.7015442959262,
buyAmountInUsd: 1005.9639175379324,
date: {date: '2021-12-07'},
sellAmount: {USD: 1000, INR: 79000}
}]
console.log(
arr.map(initialValue => {
return {
amount: initialValue.sellAmount.USD,
date: initialValue.date.date
}
})
)
The better idea would be the having an array of objects rather than array of array elements
let result = yourArray.map(each => ({ amount: each.sellAmount.USD, date: each.date.date }))
This is not related to ReactJS - just native Javascript object handling.
If your original data has the shape of an Object you can convert it into an Array like so:
const objData = { 0: {...}, 1: {...} };
const arrData = Object.entries(objData); // [[0, {...}], [1, {...}]];
From there, you can filter/map/sort your array with native array methods:
const reshapedArray = arrData.map(([key, value]) => {
return {
amount: value.sellAmount.USD,
date: value.date.date,
};
});
Then sort:
const sortedArray = reshapedArray.sort((prev, next) => {
return prev.amount - next.amount; // sort by amount ascending
});
You can of could chain these array functions and shorten the syntax a bit:
Object.entries(objData)
.map(([_, { sellAmount, date: { date } }]) => ({ amount: sellAmount.USD, date }))
.sort((a, b) => a.amount - b.amount);
So I have an array with a data of
var today = "2020-08-31"
var array = [
{
name: "Joshua",
id: 1,
date: "2020-08-31"
},
{
name: "Michael",
id: 2,
date: "2020-09-1"
}]
I want to create a sectionList that the sectionHeader title will be depending on the date today and will compare it to the date value from the array. so for example the date from the array is "2020-08-31" and today's date is same as "2020-08-31" the title should be "Today" and tomorrow is "2020-09-01" and the date from the array is still "2020-08-31" the title should be "Yesterday" is it possible?? please help me. im stuck with this. Thank you!!!!
Use the parse function from the JS Date library to parse the date hence convert it into long and then return the string (yesterday, today, tomorrow).
Add the displayDate into you array in order to loop through and display the field's value.
const today = "2020-08-31"
let array = [{
name: "Joshua",
id: 1,
date: "2020-08-31"
},
{
name: "Michael",
id: 2,
date: "2020-09-1"
}
]
array = array.map(x => ({
...x,
displayDate: (() => {
if (Date.parse(today) < Date.parse(x.date)) {
return 'yesterday';
} else if (Date.parse(today) > Date.parse(x.date)) {
return 'tomorrow';
}
return 'today';
})()
}));
console.log(array)
I am creating a calendar to view shifts in calendar.I will be getting data`s from backend as array of values
the array will be
var shift = [morning shift,10:00,15:00,10/10/2018,15/10/2018],[[noon shift,10:00,15:00,10/09/2018,15/09/2018]]
which denotes [shift name,shift start time,shift end time,shift start date, shift end date]
I have to pass this value in an object as
var repeatingEvents = [{
title:"morning shift",
start: '10:00', // a start time (10am in this example)
end: '15:00', // an end time (6pm in this example)
ranges: [{
start:new Date(10/10/2018),
end: new Date(15/10/2018),
}],
},
{
title:"morning shift",
start: '10:00', // a start time (10am in this example)
end: '15:00', // an end time (6pm in this example)
ranges: [{
start:new Date(10/09/2018),
end: new Date(15/09/2018),
}],
}],
}];
here i am having a multidimensional object.
for
apiData=[morningShift,10/09/2018,15/09/2018]
i have mapped the values and its working good
events : apiData.map(([start,end,title])=>({
start: new Date(start),
end: new Date(end+'T00:00:00-07:00'),
title,
className: 'bg-primary'})
),
How to do this for multidimentional object.I am a beginner in js and could anyone help me with this ?Thanks in advance