Skip to content

Commit

Permalink
Merge pull request #6 from moonpatel/branch1
Browse files Browse the repository at this point in the history
Branch1
  • Loading branch information
moonpatel authored Aug 31, 2022
2 parents 0e9efb5 + d8f9ae5 commit d16fea2
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 78 deletions.
68 changes: 12 additions & 56 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ const mongoose = require('mongoose')
const methodOverride = require('method-override')
const ejsMate = require('ejs-mate')
const path = require('path')
const catchAsync = require('./utils/catchAsync')
const ExpressError = require('./utils/ExpressError')
// require models
const Campground = require('./models/campgrounds')
const { campgroundSchema } = require('./schemas')
const joi = require('joi')

// routes
const campground = require('./routes/campgrounds')
const reviews = require('./routes/reviews')
// port number to listen for requests
const port = 3000

Expand All @@ -19,7 +18,7 @@ mongoose.connect('mongodb://localhost:27017/yelpcamp')
// check the status of database connection
const db = mongoose.connection
db.on("error", console.error.bind(console, "connection error"))
db.once("open", () => console.log("Database connected"))
db.once("open", () => console.log("Connected to MongoDB"))

// create an express application object
const app = express()
Expand All @@ -32,63 +31,20 @@ app.set('views', path.join(__dirname, 'views'))
app.use(express.urlencoded({ extended: true }))
app.use(methodOverride('_method'))

// validate campground object
const validateCampground = (req, res, next) => {
const { error } = campgroundSchema.validate(req.body.campground)
if (error) {
const msg = error.details.map(el => el.message).join(',')
next(new ExpressError(msg, 400))
}
else next()
}

// RECEIVE REQUESTS
// main page
app.get('/', (req, res) => {
res.render('home')
})
// campgrounds index
app.get('/campgrounds', catchAsync(async (req, res) => {
const camps = await Campground.find({})
res.render('campgrounds/index', { camps })
}))
// add new campgrounds
app.get('/campgrounds/new', (req, res) => res.render('new'))
// add new campground to server
app.post('/campgrounds', validateCampground, catchAsync(async (req, res, next) => {
const cg = new Campground(req.body.campground)
await cg.save()
res.redirect(`/campgrounds/${cg._id}`)
}))
// show individual campground
app.get('/campgrounds/:id', catchAsync(async (req, res) => {
const c = await Campground.findOne({ _id: req.params.id })
res.render('campgrounds/show', { c })
}))
// render form to edit a campground
app.get('/campgrounds/:id/edit', catchAsync(async (req, res) => {
const cg = await Campground.findById(req.params.id)
res.render('edit', { cg })
}))
// send put request to save changes
app.put('/campgrounds/:id', validateCampground, catchAsync(async (req, res) => {
const { title, location } = req.body.campground
await Campground.updateOne({ _id: req.params.id }, { title: title, location: location })
res.redirect(`/campgrounds/${req.params.id}`)
}))
// delete campground
app.delete('/campgrounds/:id', catchAsync(async (req, res) => {
await Campground.findByIdAndDelete(req.params.id)
res.redirect('/campgrounds')
}))
app.get('/', (req, res) => res.render('home'))
// campground routes
app.use('/campgrounds', campground)
// review routes
app.use('/campgrounds/:id/reviews', reviews)


// if page unavailable
// Page not found
app.all('*', (req, res, next) => {
next(new ExpressError('Page not found', 404))
})

// error handler
// all in one error handler
app.use((err, req, res, next) => {
const { message = 'Something went wrong', statusCode = 500 } = err
console.log(err)
Expand Down
8 changes: 7 additions & 1 deletion models/campgrounds.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ const campgroundSchema = new Schema({
location: String,
description: String,
price: Number,
image: String
image: String,
reviews: [
{
type: Schema.Types.ObjectId,
ref: 'Review'
}
]
})

// create a model out of campgroundSchema
Expand Down
10 changes: 10 additions & 0 deletions models/reviews.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// include mongoose
const mongoose = require('mongoose')
const Schema = mongoose.Schema

const reviewSchema = Schema({
body: String,
rating: Number
})

module.exports = mongoose.model('Review',reviewSchema)
56 changes: 56 additions & 0 deletions routes/campgrounds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const express = require('express')
const router = express.Router()
const catchAsync = require('../utils/catchAsync')
const { campgroundSchema } = require('../schemas')


const ExpressError = require('../utils/ExpressError')
const Campground = require('../models/campgrounds')

// validate campground object
const validateCampground = (req, res, next) => {
const { error } = campgroundSchema.validate(req.body.campground)
if (error) {
const msg = error.details.map(el => el.message).join(',')
throw new ExpressError(msg, 400)
}
else next()
}

// campgrounds index
router.get('/', catchAsync(async (req, res) => {
const camps = await Campground.find({})
res.render('campgrounds/index', { camps })
}))
// add new campgrounds
router.get('/new', (req, res) => res.render('new'))
// add new campground to server
router.post('/', validateCampground, catchAsync(async (req, res, next) => {
const cg = new Campground(req.body.campground)
await cg.save()
res.redirect(`/campgrounds/${cg._id}`)
}))

// show individual campground
router.get('/:id', catchAsync(async (req, res) => {
const c = await Campground.findOne({ _id: req.params.id }).populate('reviews')
res.render('campgrounds/show', { c })
}))
// render form to edit a campground
router.get('/:id/edit', catchAsync(async (req, res) => {
const cg = await Campground.findById(req.params.id)
res.render('edit', { cg })
}))
// send put request to save changes
router.put('/:id', validateCampground, catchAsync(async (req, res) => {
const { title, location } = req.body.campground
await Campground.updateOne({ _id: req.params.id }, { title: title, location: location })
res.redirect(`/campgrounds/${req.params.id}`)
}))
// delete campground
router.delete('/:id', catchAsync(async (req, res) => {
await Campground.findByIdAndDelete(req.params.id)
res.redirect('/campgrounds')
}))

module.exports = router
41 changes: 41 additions & 0 deletions routes/reviews.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const express = require('express')
const router = express.Router({ mergeParams: true })
const catchAsync = require('../utils/catchAsync')
const { reviewSchema } = require('../schemas')


const ExpressError = require('../utils/ExpressError')
const Campground = require('../models/campgrounds')
const Review = require('../models/reviews')


// validate reviews object
const validateReview = (req, res, next) => {
const { error } = reviewSchema.validate(req.body.review)
if (error) {
const msg = error.details.map(el => el.message).join(',')
throw new ExpressError(msg, 400)
}
else next()
}

// add review to server
router.post('/', validateReview, catchAsync(async (req, res) => {
console.log(req.params.id)
const campground = await Campground.findById(req.params.id)
console.log(campground)
const review = new Review(req.body.review)
campground.reviews.push(review)
await campground.save()
await review.save()
res.redirect(`/campgrounds/${req.params.id}`)
}))
// delete review
router.delete('/:reviewId', catchAsync(async (req, res, next) => {
const { id, reviewId } = req.params
await Review.findByIdAndDelete(reviewId)
await Campground.findByIdAndUpdate(id, { $pull: { reviews: reviewId } })
res.redirect(`/campgrounds/${id}`)
}))

module.exports = router
8 changes: 7 additions & 1 deletion schemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,10 @@ const campgroundSchema = joi.object({
description: joi.string().required(),
image: joi.string().required()
}).required()
module.exports.campgroundSchema = campgroundSchema
module.exports.campgroundSchema = campgroundSchema

const reviewSchema = joi.object({
body: joi.string().required(),
rating: joi.number().required().min(0).max(5)
}).required()
module.exports.reviewSchema = reviewSchema
79 changes: 59 additions & 20 deletions views/campgrounds/show.ejs
Original file line number Diff line number Diff line change
@@ -1,27 +1,66 @@
<% layout('layouts/boilerplate.ejs') %>
<div class="row">
<div class="card px-0 mb-3">
<img src="<%= c.image %>/900x600" alt="campground" class="card-img-top">
<div class="card-body">
<h5 class="card-title mb-0">
<%= c.title %>
</h5>
<small class="text-muted">
<%=c.location%>
</small>
<p class="card-text mt-3">
<%=c.description%>
</p>
<div class="col-6">
<div class="card px-0 mb-3">
<img src="<%= c.image %>/900x600" alt="campground" class="card-img-top">
<div class="card-body">
<h5 class="card-title mb-0">
<%= c.title %>
</h5>
<small class="text-muted">
<%=c.location%>
</small>
<p class="card-text mt-3">
<%=c.description%>
</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">$<%=c.price%>/night</li>
</ul>
<div class="card-body">
<a class="btn btn-primary" href="/campgrounds/<%= c._id %>/edit">Edit</a>
<form action="/campgrounds/<%= c._id %>?_method=DELETE" method="post" class="mt-2 d-inline">
<button class="btn btn-danger">Delete</button>
</form>
</div>

</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">$<%=c.price%>/night</li>
</ul>
<div class="card-body">
<!-- <a class="btn btn-primary" href="/campgrounds">Back</a> -->
<a class="btn btn-primary" href="/campgrounds/<%= c._id %>/edit">Edit</a>
<form action="/campgrounds/<%= c._id %>?_method=DELETE" method="post" class="mt-2 d-inline">
<button class="btn btn-danger">Delete</button>
</div>
<div class="col-6">
<div>
<h2>Leave a Review</h2>
<form action="/campgrounds/<%= c._id %>/reviews" method="post" class="mb-3 validated-form" novalidate>
<div class="mb-3">
<label class="form-label" for="rating">Rating</label>
<input class="form-range" type="range" min="1" max="5" name="review[rating]" id="rating"
value="0" required>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Looks bad!</div>
</div>
<div class="mb-3">
<label class="form-label" for="body">Review</label>
<textarea class="form-control" name="review[body]" id="body" cols="30" rows="3" value=""
required></textarea>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Looks bad!</div>
</div>
<button class="btn btn-success">Submit</button>
</form>
<%for(let review of c.reviews) {%>
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title mb-0">
Rating: <%= review.rating %>
</h5>
<p class="card-text mt-3">
<%= review.body %>
</p>
<form action="/campgrounds/<%=c._id%>/reviews/<%=review._id%>?_method=DELETE" method="post">
<button class="btn btn-sm btn-danger">Delete</button>
</form>
</div>
</div>
<%}%>
</div>
</div>
</div>
2 changes: 2 additions & 0 deletions views/layouts/boilerplate.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@
// Fetch all the forms we want to apply custom Bootstrap validation styles to
const forms = document.querySelectorAll('.validated-form')
console.log(forms)
// Loop over them and prevent submission
Array.from(forms)
.forEach(form => {
form.addEventListener('submit', event => {
console.log('inside validation')
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
Expand Down

0 comments on commit d16fea2

Please sign in to comment.