Javascript: stuck with comparison function - javascript

I am stuck and need help finishing this fetch request.
I need a function to check if the movie (a single object) in the request has previously been rated by the user.
The ratings are in the ratedMovies array. If the movie was rated I need the userRating property with it's value to be added to the response. If it has not been rated, I need the userRating value to be null
const ratedMovies = useStore((state) => state.ratedMovies)
const getMovieDetails = () => {
const key = `https://www.omdbapi.com/?i=${movie.imdbID}&apikey=b46dc190`
axios
.get(key)
.then((response) => {
// Here a comparison is required, to check if the movie in the response (a single object)
// has ever been rated before and its ID (imdbID) and userRating (property to be added) is
// present in the ratedMovies array
// if it is present I need the property userRating nad it's value to be added to the response
// or when it is empty, to have the userRating be null
setModalDetails(response.data)
})
.then((response) => {
console.log(modalDetails)
})
.catch((error) => console.log(error))
}
Sample axios response:
{
"Title": "Star Wars: Episode V - The Empire Strikes Back",
"Year": "1980",
"Rated": "PG",
"Released": "20 Jun 1980",
"Runtime": "124 min",
"Genre": "Action, Adventure, Fantasy",
"Director": "Irvin Kershner",
"Writer": "Leigh Brackett, Lawrence Kasdan, George Lucas",
"Actors": "Mark Hamill, Harrison Ford, Carrie Fisher",
"Plot": "After the Rebels are brutally overpowered by the Empire on the ice planet Hoth, Luke Skywalker begins Jedi training with Yoda, while his friends are pursued across the galaxy by Darth Vader and bounty hunter Boba Fett.",
"Language": "English",
"Country": "United States, United Kingdom",
"Awards": "Won 2 Oscars. 25 wins & 20 nominations total",
"Poster": "https://m.media-amazon.com/images/M/MV5BYmU1NDRjNDgtMzhiMi00NjZmLTg5NGItZDNiZjU5NTU4OTE0XkEyXkFqcGdeQXVyNzkwMjQ5NzM#._V1_SX300.jpg",
"Ratings": [
{
"Source": "Internet Movie Database",
"Value": "8.7/10"
},
{
"Source": "Rotten Tomatoes",
"Value": "94%"
},
{
"Source": "Metacritic",
"Value": "82/100"
}
],
"Metascore": "82",
"imdbRating": "8.7",
"imdbVotes": "1,209,128",
"imdbID": "tt0080684",
"Type": "movie",
"DVD": "21 Sep 2004",
"BoxOffice": "$292,753,960",
"Production": "N/A",
"Website": "N/A",
"Response": "True"
}
Sample rating:
ratedMovies = [{imdbID: 'tt0080684', userRating: 8}]

Ok if I understand it correctly it goes like this:
let data = response.data;
let newMovieId = data.imdbID;
ratedMovies.forEach((movie) => {
if(movie.imdbID === newMovieId) {
data.userRating = movie.userRating;
}
});
setModalDetails(data)
code above goes inside the axios success callback

You can use .filter function like this:
ratedMovies = [{imdbID: 'tt0080684', userRating: 8}]
notratedMovies = [{imdbID: 'tt0080111', userRating: 8}]
let result = ratedMovies.filter(obj => {
return obj.imdbID === imdb.imdbID
});
console.log(result);
let notresult = notratedMovies.filter(obj => {
return obj.imdbID === imdb.imdbID
});
console.log(notresult);

Related

replace a key value pair from a GET request without mutating the original JSON

I have a task to return some an object by name of recipe and include a list of it's ingredients and also an object that replaces the instructions with a key value pair of "numSteps": count_of_instruction_steps. I am having a hard time with removing the key of "instructions" for the result.
This is the .json file of recipes:
{
"recipes": [
{
"name": "scrambledEggs",
"ingredients": [
"1 tsp oil",
"2 eggs",
"salt"
],
"instructions": [
"Beat eggs with salt",
"Heat oil in pan",
"Add eggs to pan when hot",
"Gather eggs into curds, remove when cooked",
"Salt to taste and enjoy"
]
},
{
"name": "garlicPasta",
"ingredients": [
"500mL water",
"100g spaghetti",
"25mL olive oil",
"4 cloves garlic",
"Salt"
],
"instructions": [
"Heat garlic in olive oil",
"Boil water in pot",
"Add pasta to boiling water",
"Remove pasta from water and mix with garlic olive oil",
"Salt to taste and enjoy"
]
},
{
"name": "chai",
"ingredients": [
"400mL water",
"100mL milk",
"5g chai masala",
"2 tea bags or 20 g loose tea leaves"
],
"instructions": [
"Heat water until 80 C",
"Add milk, heat until 80 C",
"Add tea leaves/tea bags, chai masala; mix and steep for 3-4 minutes",
"Remove mixture from heat; strain and enjoy"
]
}
]
}
The task is the following:
A GET request to http://localhost:3000/recipes/details/garlicPasta should return, if recipe exists, this .json:
Response body (JSON):
{
"details":
{
"ingredients": [
"500mL water",
"100g spaghetti",
"25mL olive oil",
"4 cloves garlic",
"Salt"
],
"numSteps":5
}
}
Status: 200
And should return this if it does not exist:
Response body (JSON): {}
Status: 200
This is what I am actually getting:
{
name: "garlicPasta",
ingredients: [
"500mL water",
"100g spaghetti",
"25mL olive oil",
"4 cloves garlic",
"Salt"
],
instructions: {
numSteps: 5
}
}
My code is the following:
app.get('/recipes/details/:name', (req, res) => {
let count = 0
const numSteps = {}
const recipe = recipes.find(r => r.name === req.params.name)
const instructions = recipes.map(r => {
if(r.name === req.params.name){
for(let instruction of r.instructions){
count += 1
}
}
})
recipe.instructions = {"numSteps": count}
res.status(200).send(recipe);
})
I wouldn't try to return a modified "recipe" object since the shape of the response you need is different. You can use your existing code to find the correct recipe, and then just create a new object with the response properties you want. Note that you can just use recipe.instructions.length to know how many steps there are.
app.get('/recipes/details/:name', (req, res) => {
let count = 0;
const recipe = recipes.find(r => r.name === req.params.name);
const output = {
details: {
ingredients: recipe.ingredients,
numSteps: recipe.instructions.length
}
};
res.status(200).send(output);
})
You're not creating the details property, and you're adding an instructions property in the result that you don't want.
There's no need to loop to count numSteps, you can just use r.instructions.length. And once you find the recipe with recipes.find(), you don't need another loop to find the recipe name.
You're not checking whether the recipe can be found, so that you return {} in that case.
app.get('/recipes/details/:name', (req, res) => {
const recipe = recipes.find(r => r.name === req.params.name);
let result = {};
if (recipe) {
result.details = {
ingredients: recipe.ingredients,
numSteps: recipe.instructions.length
};
}
res.status(200).send(recipe);
})

getTime() method behaves differently in js

I have an array of object like :
[
{
"order_id": 1,
"customer": "Karita Klimochkin",
"country": "Sweden",
"address": "8978 Westridge Park",
"product_title": "Yellow-bellied marmot",
"product_description": "Bread - Flat Bread",
"date": "21/08/2020",
"status": "Delivered"
},
{
"order_id": 2,
"customer": "Ferne Roman",
"country": "China",
"address": "1370 Ridge Oak Pass",
"product_title": "Two-toed sloth",
"product_description": "Asparagus - White, Fresh",
"date": "24/07/2020",
"status": "Completed"
}
]
I want to sort objects by date. so when I use getTime() method it gives me different result.
orders.map(order => new Date(order.date).getTime())
results are :
1628100000000
NaN
What is the problem here?
You need to convert the date to mm/dd/yyyy format from dd/mm/yyyy so that JS can understand it properly
orders.map(order => {
const parts= order.date.split("/")
return new Date(`${parts[1]}/${parts[0]}/${parts[2]}`).getTime()
})
You cannot count on the default date parser to parse your DD/MM/YYYY format correctly. Parsing date strings through the constructor in this way is highly discouraged because it is implementation-dependent. Different browsers/runtimes will parse dates differently.
Instead, manually parse the date yourself and then construct the date object:
orders.map(order => {
const [d, m, y] = order.date.split('/');
return +new Date(+y, m-1, +d);
})
Friendly reminder: do you have a sorting functionality yet? .map is just an iteration through your array.
More about map: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Add a sort function based on your date(properly parsed) property and return a new array would help.
The dates are in the wrong format:
// from: "21/08/2020"
let format = obj.date.split('/').reverse().join('-')
// to: "2020-08-21"
In order to be sortable, dates must be in ms since Jan 1, 1970. Assign the new value to a new key:
obj.pDate = Date.parse(format);
Sort by the new key/value:
let results = orders.sort((a, b) => a.pDate = b.pDate)
Then remove all of the new key/values:
results.map(order => delete order.pDate)
const data = [{
"order_id": 1,
"customer": "Karita Klimochkin",
"country": "Sweden",
"address": "8978 Westridge Park",
"product_title": "Yellow-bellied marmot",
"product_description": "Bread - Flat Bread",
"date": "21/08/2020",
"status": "Delivered"
},
{
"order_id": 2,
"customer": "Ferne Roman",
"country": "China",
"address": "1370 Ridge Oak Pass",
"product_title": "Two-toed sloth",
"product_description": "Asparagus - White, Fresh",
"date": "24/07/2020",
"status": "Completed"
}, {
"order_id": 3,
"customer": "zer00ne",
"country": "US",
"address": "123 Main St",
"product_title": "Jackalope",
"product_description": "Chili Cheese Fries",
"date": "12/05/2020",
"status": "Delivered"
},
];
const sortOrders = orders => {
let result = orders.sort((a, b) => {
a.pDate = Date.parse(a.date.split('/').reverse().join('-'));
b.pDate = Date.parse(b.date.split('/').reverse().join('-'));
return a.pDate - b.pDate;
})
result.map(order => delete order.pDate);
return result;
};
console.log(sortOrders(data));

JSON.stringify not working in my map method in template literals

I am trying to map through some data and display the values from the objects I am mapping through, but it keeps return "[object Object]", usually I just wrap it in JSON.stringify but that isn't working here, what am I doing wrong? Here's my code:
const ListingItem = (props: any) => {
const MOVIE_POSTER_API_URL = "https://image.tmdb.org/t/p/w92/";
const [openMovieDbData, setOpenMovieDbData] = useState<Array<any>>([]);
const [openMovieDbRatings, setOpenMovieDbRatings] = useState([]);
useEffect((): any => {
axios.get(`http://www.omdbapi.com/?t=${props.movie.title}&y=${props.movie.release_date && props.movie.release_date.substr(0, 4)}&apikey=${process.env.REACT_APP_OPEN_MOVIE_API_KEY}`)
.then(response => {
setOpenMovieDbData(response.data);
setOpenMovieDbRatings(response.data.Ratings);
})
.catch((error) => console.log('Open Movie DB HTTP GET Request Error response:', error))
}, [])
return (
<ListItem key={props.movie.id}>
{props.movie.backdrop_path ?
<ListItemAvatar>
<Avatar src={MOVIE_POSTER_API_URL + props.movie.backdrop_path} />
</ListItemAvatar> :
<ListItemIcon>
<Avatar>
<LocalMoviesIcon />
</Avatar>
</ListItemIcon>
}
<ListItemText
primary={props.movie.title}
secondary={`${props.movie.overview} Released in ${props.movie.release_date ? props.movie.release_date.substr(0, 4) : 'N/A'}
${openMovieDbRatings ? openMovieDbRatings.map((rating: any) => <div>{JSON.stringify(rating.Source)}: {JSON.stringify(rating.Value)}</div>) : 'No Reviews'}
Rated: ${openMovieDbData['Rated'] ? openMovieDbData['Rated'] : 'N/A'}
`
}
/>
</ListItem>
)
}
This is an example of what will get returned, in place of [object Object] should be the object values I am trying to access:
Example of response data:
{
"Title": "Braveheart",
"Year": "1995",
"Rated": "R",
"Released": "24 May 1995",
"Runtime": "178 min",
"Genre": "Biography, Drama, History, War",
"Director": "Mel Gibson",
"Writer": "Randall Wallace",
"Actors": "James Robinson, Sean Lawlor, Sandy Nelson, James Cosmo",
"Plot": "Scottish warrior William Wallace leads his countrymen in a rebellion to free his homeland from the tyranny of King Edward I of England.",
"Language": "English, French, Latin, Scottish Gaelic, Italian",
"Country": "USA",
"Awards": "Won 5 Oscars. Another 28 wins & 33 nominations.",
"Poster": "https://m.media-amazon.com/images/M/MV5BMzkzMmU0YTYtOWM3My00YzBmLWI0YzctOGYyNTkwMWE5MTJkXkEyXkFqcGdeQXVyNzkwMjQ5NzM#._V1_SX300.jpg",
"Ratings": [{
"Source": "Internet Movie Database",
"Value": "8.3/10"
}, {
"Source": "Rotten Tomatoes",
"Value": "78%"
}, {
"Source": "Metacritic",
"Value": "68/100"
}],
"Metascore": "68",
"imdbRating": "8.3",
"imdbVotes": "944,923",
"imdbID": "tt0112573",
"Type": "movie",
"DVD": "N/A",
"BoxOffice": "N/A",
"Production": "Icon Entertainment International, Twentieth Century Fox, Ladd Company, Paramount Pictures, B.H. Finance C.V.",
"Website": "N/A",
"Response": "True"
}
i think the issue is here,
secondary={`${props.movie.overview} Released in ${props.movie.release_date ? props.movie.release_date.substr(0, 4) : 'N/A'}
${openMovieDbRatings ? openMovieDbRatings.map((rating: any) => <div>{JSON.stringify(rating.Source)}: {JSON.stringify(rating.Value)}</div>) : 'No Reviews'}
Rated: ${openMovieDbData['Rated'] ? openMovieDbData['Rated'] : 'N/A'}
`}
#1: (main)
${openMovieDbRatings
? openMovieDbRatings.map((rating: any) =>
<div>{JSON.stringify(rating.Source)}: {JSON.stringify(rating.Value)}</div>
)
: 'No Reviews'}
You are mapping openMovieDbRatings and making em ReactElements (aka Objects) by wrapping those inside divs. But, Then u directly pass them to string. This is causing the [object object] thing
#2:
The Rating Object,
"Ratings": [{
"Source": "Internet Movie Database",
"Value": "8.3/10"
}, {
"Source": "Rotten Tomatoes",
"Value": "78%"
}, {
"Source": "Metacritic",
"Value": "68/100"
}],
Here, The Rating Value & Source are strings. So, it unnecessary to JSON.stringify them,
<div>{JSON.stringify(rating.Source)}: {JSON.stringify(rating.Value)}</div>
My Solution,
<ListItemText
primary={props.movie.title}
secondary={
<>
{props.movie.overview} Released in{' '}
{props.movie.release_date
? props.movie.release_date.substr(0, 4)
: 'N/A'}{' '}
{openMovieDbRatings
? openMovieDbRatings.map((rating: any) => (
<div>
{rating.Source}: {rating.Value}
</div>
))
: 'No Reviews'}
Rated:{' '}
{openMovieDbData['Rated'] ? openMovieDbData['Rated'] : 'N/A'}
</>
}
/>
Simply, use React.Fragments.

Filter the JSON object and write the results in the local .json file

I've fetched an API and got a JSON object that I need to filter through and store in a new local json file.
the results get returned, but I can't figure out a way to filter through the json file (data) and correctly write it into the new newfile.json file.
.then(
json => {
const data = JSON.stringify(json)
const filtered = data.map( //some filter function )
fs.writeFile('src/data/newfile.json', filtered, 'utf8', function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
Here is the example of the json data I'm getting from the array of surveys.
{
"surveyId": 515315,
"reviewId": "34152",
"transactionInfo": {
"transactionRef": "1806001511991",
"transactionCity": "Plymouth",
"transactionState": "MN",
"transactionType": null,
"customerFirstName": "Kristine",
},
"serviceProviderInfo": {
"serviceProviderName": "Lobster",
"serviceProviderEmail": "lobster#bayeq.com",
"serviceProviderId": 43346,
"serviceProviderOfficeName": "Oakdale - 30152501",
"serviceProviderRegionName": "Minnesota - Chacich",
"serviceProviderOfficeId": 721581,
"serviceProviderRegionId": 151563
},
"review": {
"source": "encompass",
"rating": "5.0",
"summary": null,
"description": "He was fantastic ",
"agreedToShare": true,
"verifiedCustomer": true,
"retakeSurvey": false,
"surveyResponses": [
{
"question": "How would you rate the service and support you received?",
"type": "Numeric",
"answer": "5"
},
{
"question": "Please rate the level of advice and communication you received from [name].",
"type": "Numeric",
"answer": "5"
},
{
"question": "How likely are you to refer friends and family to [name]?",
"type": "Numeric",
"answer": "10"
},
{
"question": "How would you rate your overall experience?",
"type": "Experience",
"answer": "Great"
}
],
"reportedAbusive": false
},
"reviewStatus": "completed"
}
How do I filter through this and create a new JSON file with the structure like
{
"email": "foo#bar.com",
"rating": 4.56,
"testimonials": [{
"description": "Fugiat ut sed occaecat.",
"firstname": "Bob",
"city": "Bananatown",
"state": "TH"
}]
}
Here I used jquery
var datat = {
"surveyId": 515315,
"reviewId": "34152",
"transactionInfo": {
"transactionRef": "1806001511991",
"transactionCity": "Plymouth",
"transactionState": "MN",
"transactionType": null,
"customerFirstName": "Kristine",
},
"serviceProviderInfo": {
"serviceProviderName": "Lobster",
"serviceProviderEmail": "lobster#bayeq.com",
"serviceProviderId": 43346,
"serviceProviderOfficeName": "Oakdale - 30152501",
"serviceProviderRegionName": "Minnesota - Chacich",
"serviceProviderOfficeId": 721581,
"serviceProviderRegionId": 151563
},
"review": {
"source": "encompass",
"rating": "5.0",
"summary": null,
"description": "He was fantastic ",
"agreedToShare": true,
"verifiedCustomer": true,
"retakeSurvey": false,
"surveyResponses": [
{
"question": "How would you rate the service and support you received?",
"type": "Numeric",
"answer": "5"
},
{
"question": "Please rate the level of advice and communication you received from [name].",
"type": "Numeric",
"answer": "5"
},
{
"question": "How likely are you to refer friends and family to [name]?",
"type": "Numeric",
"answer": "10"
},
{
"question": "How would you rate your overall experience?",
"type": "Experience",
"answer": "Great"
}
],
"reportedAbusive": false
},
"reviewStatus": "completed"
};
datat.review.surveyResponses = datat.review.surveyResponses.filter(function (a) {
return a.answer === "10";
});
var sd = datat.review.surveyResponses[0].question;
alert(sd);
I'm making some guesses here. As has been pointed out, there are so many discrepancies between the sample input and sample output that readers don't have confidence in the mapping inferences that are available. The correlations I've relied upon are inconsistent with the structure of the sample output, but these are the only options that are even plausible.
Also, I think you probably don't want to stringify the incoming data. You want it to be an object, so you can directly address the data; if the data is coming in as a string, you need to parse it into an object with JSON.parse
Here's something that might work. I've chained .then calls to make it easier to insert new steps and reorder them if necessary. I've omitted any error handling, but if you're parsing strings that you receive from the internet, you'll want to have something that can handle the error that will be thrown when the input string isn't valid JSON.
.then(string => JSON.parse(string)) // only needed if your earlier promise returns a string
.then(json => ({
email: json.serviceProviderInfo.serviceProviderEmail,
rating: json.review.rating,
testimonials: [{
description: json.review.description,
firstname: json.transactionInfo.customerFirstName,
city: json.transactionInfo.transactionCity,
state: json.transactionInfo.transactionState
}]
}))
.then(summary => {
return fs.writeFile('src/data/newfile.json', JSON.stringify(summary), 'utf8', function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
return true
})
})

'addEventListener' of undefined

I am trying to make it so that when the user clicks one of the 30 teams, the team that is clicked is queried with the Giphy API.
The giphy API key used is the public API key.
// all 30 NBA Teams //
var predefinedButtons = [
"Atlanta Hawks",
"Boston Celtics",
"Brooklyn Nets",
"Charlotte Hornets",
"Chicago Bulls",
"Cleveland Cavaliers",
"Dallas Mavericks",
"Denver Nuggets",
"Detroit Pistons",
"Golden State Warriors",
"Houston Rockets",
"Indiana Pacers",
"LA Clippers",
"LA Lakers ",
"Memphis Grizzlies",
"Miami Heat",
"Milwaukee Bucks",
"Minnesota Timberwolves",
"New Orleans Hornets",
"New York Knicks",
"Oklahoma City Thunder",
"Orlando Magic",
"Philadelphia Sixers",
"Phoenix Suns",
"Portland Trail Blazers",
"Sacramento Kings",
"San Antonio Spurs",
"Toronto Raptors",
"Utah Jazz",
"Washington Wizards"
];
console.log(predefinedButtons);
// The Buttons added dynamically //
var $nbaTeams;
var nbaButtons = function nbaGiphy() {
for ( i in predefinedButtons ) {
$nbaTeams = $("<button class='.btn btn-secondary' 'onclick='getNBAGiphy()''>").text(predefinedButtons[i]);
$("#nbaTags").append($nbaTeams);
}
}
nbaButtons();
// The code below is where the event listener is 'undefined' //
function getNBAGiphy() {
var nbaSearchGifs;
nbaSearchGifs.addEventListener('click', function() {
nbaSearchGifs = $(".btn btn-secondary").val();
xhr = $.get("http://api.giphy.com/v1/gifs/search?q="+nbaSearchGifs+"&api_key=dc6zaTOxFJmzC&limit=15");
xhr.done(function (response) {
console.log("success got data", response);
nbaTeamData = response.data
$("#giphyContent").html("");
console.log(nbaSearchGifs);
})
});
}
getNBAGiphy();
You are declaring variable and you have not assigned any value to it. So by default it is undefined. Code i am referring to is:
function getNBAGiphy() {
var nbaSearchGifs;
nbaSearchGifs.addeventListner

Categories

Resources