Skip to content

Commit

Permalink
Merge pull request #9 from bmarieay/develop-branch
Browse files Browse the repository at this point in the history
Integrated new filter feature
  • Loading branch information
bmarieay authored Mar 2, 2022
2 parents ac75c01 + 43b4ede commit daa4fbc
Show file tree
Hide file tree
Showing 11 changed files with 256 additions and 108 deletions.
16 changes: 11 additions & 5 deletions ReadMe.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
# YelpCamp United States
<hr>
This is my first full stack CRUD project that allows users to view, post, edit, delete, and leave reviews on the campgrounds.
<br><br>
<b>Features that I added/will be added on top of Colt Steele's Web Development Bootcamp: </b>
<br>

1.**[NPS API](https://www.nps.gov/subjects/developer/guides.htm)** - I integrated real campgrounds in the United States using an API.<br>
<<<<<<< HEAD
1. **☀️light and 🌙dark mode** - I used JS DOM Manipulation, localStorage, and Cookies to implement a theme feature<br>
2. **🌳My campgrounds** - This feature allows users to show the campgrounds they uploaded to YelpCamp! <br>
3. **📄pagination feature** - I also used DOM Manipulation, cookies, and Mongoose to implement pagination. This augments the performance by loading only few datas the the user wants rather than loading a whole single resource.<br>
4. 🔍**Search Feature** ➡️ <i>Coming soon!</i>

=======
2. **☀️light and 🌙dark mode** - I used JS DOM Manipulation, localStorage, and Cookies to implement this themed feature.<br>
3. **🌳My campgrounds** - This feature allows users to show the campgrounds they uploaded to YelpCamp! <br>
4. **📄pagination feature** - I also used DOM Manipulation, cookies, and Mongoose to implement pagination. This augments the performance by loading only few datas the user wants rather than loading a whole single resource.<br>
5. 🔍**Filter Campgrounds Feature** - allows users to look for campgrounds located on a certain state. ➡️ <i>Coming soon!</i>
>>>>>>> develop-branch
<hr>

## 🔨Stacks
YelpCamp is built with **MEN** (*Mongo, Express, and Node*) stack.
<hr>


## 👀 Previews
#### Login
Expand Down Expand Up @@ -57,7 +63,7 @@ YelpCamp is built with **MEN** (*Mongo, Express, and Node*) stack.
#### Reviews
<img src="assets/imgs/review.png" width="100%" alt="Home page">

<hr>


## 🧰Tools

Expand All @@ -69,7 +75,7 @@ YelpCamp is built with **MEN** (*Mongo, Express, and Node*) stack.
5. #### Embedded Javascript
6. #### Axios
7. #### Joi
<hr>


## 💻 To run on your local machine:
### Prerequisties:
Expand Down
124 changes: 88 additions & 36 deletions controllers/campgrounds.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,99 @@ const User = require("../models/user")
const { cloudinary } = require("../cloudinary")
const mbxGeocoding = require("@mapbox/mapbox-sdk/services/geocoding");
const mapBoxToken = process.env.MAPBOX_TOKEN;
const axios = require("axios");
const geocoder = mbxGeocoding({ accessToken: mapBoxToken });
mbxGeocoding({ accessToken: mapBoxToken });
//TODO: MAKE A MIDDLEWARE FOR RENDERING INDEX
const {config, reverseGeo} = require("../tools/index");
/*
** TODO:IMPROVE ACCESSIBLITY
*/
module.exports.index = async (req, res) => {
const result = {};
result.results = [];
const allCampgrounds = await Campground.find({});
result.allItemsFetched = allCampgrounds.map( camp => camp).length;
const max = Math.ceil(result.allItemsFetched / 20.0);
let {page, limit} = req.query;
let {page, limit, q} = req.query;
page = parseInt(page);
limit = parseInt(limit);
if(!page || page < 0){
page=1;//very first page
}
if (page > max){
page=max;
}
if(!limit){
limit=20;
}
const startIndex = (page - 1) * limit;
const endIndex = page * limit;
const campgrounds = await Campground.find().limit(limit).skip(startIndex);
//get info for the pagination(prev and next)
if(startIndex > 0){
result.previous = {
page: page - 1,
limit
limit = parseInt(limit);
if(!page || page < 0){
page=1;//very first page
}
}
if(endIndex < result.allItemsFetched){
result.next = {
page: page + 1,
limit
if (page > max){
page=max;
}
if(!limit){
limit=20;
}
const startIndex = (page - 1) * limit;
const endIndex = page * limit;
//get info for the pagination(prev and next)
if(startIndex > 0){
result.previous = {
page: page - 1,
limit
}
}
if(endIndex < result.allItemsFetched){
result.next = {
page: page + 1,
limit
}
}
res.cookie('currentPage', page);

if(!q){
//if there is no filter passed just render all campgrounds
res.clearCookie('filter');
const campgrounds = await Campground.find().limit(limit).skip(startIndex);
result.results = campgrounds;
return res.render('campgrounds/index', {result});
}

//user filtered campgrounds
const queried = await axios.get(`https://developer.nps.gov/api/v1/campgrounds?limit=50&stateCode=${q}`, config);
let matchedCampground;
result.filter = q;
if(queried.data.data.length) {
//If found: save to database or just render if it already exists
const campPromises = queried.data.data.map(async function(camp) {
//make a more narrow filter for matching
if(camp.images[0]){
matchedCampground = await Campground.find({$and:[{title: camp.name},{description: camp.description}]});
//make a new campground
if(matchedCampground.length){
result.results.push(...matchedCampground);
} else {
const campground = new Campground({
location: camp.addresses[0] ?
`${camp.addresses[0].line1} ${camp.addresses[0].city} ${camp.addresses[0].stateCode}`:
await reverseGeo([Number.parseFloat( camp.longitude, 10), Number.parseFloat( camp.latitude, 10)]),

title: camp.name,

description: camp.description,
//assign no price if there is no cost
price: camp.fees[0] ? camp.fees[0].cost : 0,

images: camp.images.map(c => ({ url: c.url})),

geometry: {
type: 'Point',
coordinates: [
camp.longitude,
camp.latitude
]
}
})
await campground.save();
result.results.push(campground);
}
}
});
await Promise.all(campPromises);
}
res.cookie('currentPage', page);
result.results = campgrounds;
//for determining max number of pages
res.render('campgrounds/index', {result});
// res.send(result);
res.render('campgrounds/index', {result})
}

module.exports.renderNewForm = (req, res) => {
Expand Down Expand Up @@ -155,17 +207,17 @@ module.exports.editCampground = async (req, res) => {
const {id} = req.params;
//make this shorter later
const campground = await Campground.findByIdAndUpdate(id, {...req.body.campground});//spread each properties
const imgs = req.files.map(f => ({ url: f.path, filename: f.filename }))
campground.images.push(...imgs)
const imgs = req.files.map(f => ({ url: f.path, filename: f.filename }));
campground.images.push(...imgs);
await campground.save();
if(req.body.deleteImages){
for(let filename of req.body.deleteImages){
await cloudinary.uploader.destroy(filename)
await cloudinary.uploader.destroy(filename);
}
await campground.updateOne({$pull: {images: {filename: {$in: req.body.deleteImages}}}})
await campground.updateOne({$pull: {images: {filename: {$in: req.body.deleteImages}}}});
}
req.flash('success', 'Successfully updated campground!')
res.redirect(`/campgrounds/${campground._id}`)
req.flash('success', 'Successfully updated campground!');
res.redirect(`/campgrounds/${campground._id}`);
}

module.exports.deleteCampground = async (req, res) => {
Expand Down
6 changes: 2 additions & 4 deletions models/campground.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ const ImageSchema = new Schema({
ImageSchema.virtual('thumbnail').get(function () {
return this.url.replace('/upload', '/upload/w_200')
})
ImageSchema.virtual('indexSize').get(function () {
return this.url.replace('/upload', '/upload/w_415,h_280')
})

ImageSchema.virtual('showSize').get(function () {
return this.url.replace('/upload', '/upload/h_470,w_600')
return this.url.replace('/upload', '/upload/h_480')
})

const opts = {
Expand Down
28 changes: 8 additions & 20 deletions public/javascripts/pagination.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ const nextBtn = document.querySelector('.page-next');
const previousContainer = document.querySelector('.prev-btn');
const nextContainer = document.querySelector('.next-btn');
let max = Math.ceil(resultLength / 20.0);
console.log("max page:", max, " length result:", resultLength)
//update total later according to data

const pageNumber = (total, max, current) => {
const half = Math.round(max / 2);
console.log("total:", total)
console.log("half:", half, " current:", current)
let to = max;

if(current + half >= total){
Expand All @@ -19,28 +17,21 @@ const pageNumber = (total, max, current) => {
}

let from = to - max;
console.log("from: ", from, " to: ", to)

if(current <= 1){
previousContainer.classList.add('disabled');
previousContainer.setAttribute('tabindex', '-1');
} else {
previousContainer.removeAttribute('tabindex');
previousContainer.classList.remove('disabled');
// prevBtn.classList.remove('text-muted');

}
// alert(current);
// alert(total);

if(current === total){
// nextBtn.classList.add('text-muted');
// nextBtn.removeAttribute('href');
nextContainer.classList.add('disabled')
} else {
nextContainer.classList.remove('disabled');
}


return Array.from({length: max}, (_, i) => (i + 1) + from)
}

Expand All @@ -50,32 +41,29 @@ initialize();//initialize everything for new load

function initialize (){
let arrayofBtns = pageNumber(max, 5, readCookie());
console.log(arrayofBtns)
generateButtons(pageButton, arrayofBtns);
}


function readCookie() {
var allcookies = document.cookie;
let allcookies = document.cookie;
let key, value;

// Get all the cookies pairs in an array
cookiearray = allcookies.split(';');

// Now take key value pair out of this array
for(var i=0; i<cookiearray.length; i++) {
for(let i=0; i<cookiearray.length; i++) {
key = cookiearray[i].split('=')[0];
if(key === 'currentPage'){
value = parseInt(cookiearray[i].split('=')[1]);
}
}
return value;
}
}

//calls the new list of pages
function renderCorrectPages(currentPage){
//set the new page
// localStorage.setItem("currentPage", currentPage);
document.cookie = `currentPage=${currentPage}`;
initialize();
}
Expand Down Expand Up @@ -114,7 +102,7 @@ prevBtn.addEventListener('click', function() {

})

//next button
nextBtn.addEventListener('click', function() {
if(readCookie() < max){
paginationHandler.call(
Expand All @@ -125,10 +113,10 @@ nextBtn.addEventListener('click', function() {
}
})

//apply accent color to current page
for(let button of pageButton){
if(parseInt(button.innerText) === readCookie()){
button.classList.add('active-btn');
break;
}
}

}
15 changes: 15 additions & 0 deletions public/javascripts/searchMode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const options = document.querySelectorAll('option');
const stateLabel = document.querySelector('.state-label')
let state;
const stateCode = filter;

//apply selected attribute to filtered state
for(let option of options){
if(option.getAttribute('value') == stateCode){
state = option.innerText;
option.selected = true;
break;
}
}

stateLabel.innerText = state;
12 changes: 11 additions & 1 deletion public/stylesheets/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@
border-color: var(--univ-light);
}

.form-select{
width: max-content;
background-color: var(--univ-light);
}

.form-select.dark-theme{
background-color: var(--univ-dark);
color: var(--univ-light);
}

#map, #cluster-map{
width: 100%;
}
Expand All @@ -125,4 +135,4 @@
#map{
margin: 0;
}
}
}
18 changes: 1 addition & 17 deletions seeds/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const axios = require("axios");
const key = process.env.API_KEY;
const mainAuth = process.env.OWNER_ID;
const { cloudinary } = require("../cloudinary");
const {reverseGeo} = require("../tools/index");
// const mainAuth = '62040b04c7e98a10d8c2d8ac';

//get the model
Expand Down Expand Up @@ -50,23 +51,6 @@ const processDatas = async () => {
}
}

const reverseGeo = async (coordinates) => {
try {
const geoData = await geocoder.reverseGeocode({
query: coordinates,
limit: 1
}).send()

if(geoData.body.features[0]){
return geoData.body.features[0].text;
} else{
return 'NO LOCATION'
}
} catch (error) {
console.log("ERROR!:", error)
}
}

async function upload(images, camp){
for(let i =0; i< images.length; i++){
try {
Expand Down
Loading

0 comments on commit daa4fbc

Please sign in to comment.