diff --git a/src/routes/events/list-events.js b/src/routes/events/list-events.js index 9521d85..7450093 100644 --- a/src/routes/events/list-events.js +++ b/src/routes/events/list-events.js @@ -1,5 +1,5 @@ const moment = require('moment'); - +const axios = require('axios'); const { Event } = require('../../models/event'); const { validateListEvents } = require('./validations'); @@ -41,7 +41,69 @@ module.exports = async (req, res, next) => { eventsQuery.startDate = { $lte: beforeDate }; } - let sortBy = queryParams.sortBy || '-startDate'; + const sortObj = {}; + if (queryParams.sortReviews) { + sortObj.reviewsAmount = parseFloat(queryParams.sortReviews); + } + + if (queryParams.sortDate) { + sortObj.startDate = parseFloat(queryParams.sortDate); + } else { + sortObj.startDate = -1; + } + + const EQUATORIAL_RADIUS = 3963.2; + if (queryParams.location && queryParams.radius) { + if (queryParams.keywords) { + axios + .get( + `https://maps.googleapis.com/maps/api/geocode/json?address=${ + queryParams.keywords + }&key=${process.env.PLACES_API_KEY}` + ) + .then(res => { + const locationObj = res.data.results[0].geometry.location; + const coordinates = [locationObj.lat, locationObj.lng]; + eventsQuery.location = { + $geoWithin: { + $centerSphere: [ + [coordinates[1], coordinates[0]], + parseFloat(queryParams.radius) / EQUATORIAL_RADIUS + ] + } + }; + }) + .catch(error => { + console.log(error); + }); + } else { + const coordinates = queryParams.location.split(','); + eventsQuery.location = { + $geoWithin: { + $centerSphere: [ + [parseFloat(coordinates[1]), parseFloat(coordinates[0])], + parseFloat(queryParams.radius) / EQUATORIAL_RADIUS + ] + } + }; + } + } + + if ( + queryParams.hideZeroReviews && + parseFloat(queryParams.hideZeroReviews) === 1 + ) { + eventsQuery.reviewsAmount = { $gte: 1 }; + } + + if ( + queryParams.hideInactiveMapathons && + parseFloat(queryParams.hideInactiveMapathons) === 1 + ) { + eventsQuery.startDate = { $lte: new Date() }; + eventsQuery.endDate = { $gte: new Date() }; + } + let page = queryParams.page ? queryParams.page - 1 : 0; const pageLimit = queryParams.pageLimit || 12; @@ -60,9 +122,10 @@ module.exports = async (req, res, next) => { poster: 1, reviewsAmount: 1, reviewsGoal: 1, - startDate: 1 + startDate: 1, + location: 1 }) - .sort(sortBy) + .sort(sortObj) .skip(page * pageLimit) .limit(pageLimit), Event.find(eventsQuery).count() @@ -89,7 +152,7 @@ module.exports = async (req, res, next) => { lastPage, pageLimit, total, - sortBy, + sortObj, results: events }); }; diff --git a/src/routes/events/validations.js b/src/routes/events/validations.js index 2b15620..c11a4c2 100644 --- a/src/routes/events/validations.js +++ b/src/routes/events/validations.js @@ -485,6 +485,73 @@ module.exports = { } } + if (queryParams.sortReviews) { + if (!isNumber(queryParams.sortReviews)) { + errors.sortReviews = 'Should be a number'; + } else if ( + parseFloat(queryParams.sortReviews) !== 1 && + parseFloat(queryParams.sortReviews) !== -1 + ) { + errors.sortReviews = 'Should be 1 (ascending) or -1 (descending)'; + } + } + + if (queryParams.sortDate) { + if (!isNumber(queryParams.sortDate)) { + errors.sortDate = 'Should be a number'; + } else if ( + parseFloat(queryParams.sortDate) !== 1 && + parseFloat(queryParams.sortDate) !== -1 + ) { + errors.sortDate = 'Should be 1 (ascending) or -1 (descending)'; + } + } + + if (queryParams.location) { + const location = queryParams.location.split(','); + + if (location.length !== 2) { + errors.location = 'Should have two coordinates'; + } else if (!location[0]) { + errors.location = 'Latitude is required'; + } else if (!isNumber(location[0])) { + errors.location = 'Latitude should be a number'; + } else if ( + parseFloat(location[0]) < -90 || + parseFloat(location[0]) > 90 + ) { + errors.location = 'Latitude value out of bounds'; + } else if (!location[1]) { + errors.location = 'Longitude is required'; + } else if (!isNumber(location[1])) { + errors.location = 'Longitude should be a number'; + } else if ( + parseFloat(location[1]) < -180 || + parseFloat(location[1]) > 180 + ) { + errors.location = 'Longitude value out of bounds'; + } + } + + if (queryParams.radius) { + if (!isNumber(queryParams.radius)) { + errors.radius = 'Should be a number'; + } else if (parseFloat(queryParams.radius) <= 0) { + errors.radius = 'Radius should be greater than 0 miles'; + } + } + + if (queryParams.hideZeroReviews) { + if (!isNumber(queryParams.hideZeroReviews)) { + errors.hideZeroReviews = 'Should be a number'; + } else if ( + parseFloat(queryParams.hideZeroReviews) !== 1 && + parseFloat(queryParams.hideZeroReviews) !== 0 + ) { + errors.hideZeroReviews = 'Should be 0 (false) or 1 (true)'; + } + } + return { errors, isValid: isEmpty(errors) }; } };