Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# Dependency directory
node_modules
node_modules

.env
2 changes: 1 addition & 1 deletion app_api/controllers/locations.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ module.exports.locationsListByDistance = function(req, res) {
maxDistance: theEarth.getRadsFromDistance(maxDistance),
num: 10
};
if (!lng || !lat || !maxDistance) {
if ((!lng && lng!==0) || (!lat && lat!==0) || ! maxDistance) {
console.log('locationsListByDistance missing params');
sendJSONresponse(res, 404, {
"message": "lng, lat and maxDistance query parameters are all required"
Expand Down
4 changes: 2 additions & 2 deletions app_api/models/locations.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
var mongoose = require('mongoose');

var reviewSchema = new mongoose.Schema({
author: String,
author: {type: String, required: true},
rating: {
type: Number,
required: true,
min: 0,
max: 5
},
reviewText: String,
reviewText: {type: String, required: true},
createdOn: {
type: Date,
"default": Date.now
Expand Down
264 changes: 181 additions & 83 deletions app_server/controllers/locations.js
Original file line number Diff line number Diff line change
@@ -1,92 +1,190 @@
var request = require('request');
var apiOptions = {
server : "http://localhost:3000"
};
if (process.env.NODE_ENV === 'production') {
apiOptions.server = "https://getting-mean-loc8r.herokuapp.com";
}

var _isNumeric = function (n) {
return !isNaN(parseFloat(n)) && isFinite(n);
};

var _formatDistance = function (distance) {
var numDistance, unit;
if (distance && _isNumeric(distance)) {
if (distance > 1) {
numDistance = parseFloat(distance).toFixed(1);
unit = 'km';
} else {
numDistance = parseInt(distance * 1000,10);
unit = 'm';
}
return numDistance + unit;
} else {
return "?";
}
};

var _showError = function (req, res, status) {
var title, content;
if (status === 404) {
title = "404, page not found";
content = "Oh dear. Looks like we can't find this page. Sorry.";
} else if (status === 500) {
title = "500, internal server error";
content = "How embarrassing. There's a problem with our server.";
} else {
title = status + ", something's gone wrong";
content = "Something, somewhere, has gone just a little bit wrong.";
}
res.status(status);
res.render('generic-text', {
title : title,
content : content
});
};

var renderHomepage = function(req, res, responseBody){
var message;
if (!(responseBody instanceof Array)) {
message = "API lookup error";
responseBody = [];
} else {
if (!responseBody.length) {
message = "No places found nearby";
}
}
res.render('locations-list', {
title: 'Loc8r - find a place to work with wifi',
pageHeader: {
title: 'Loc8r',
strapline: 'Find places to work with wifi near you!'
},
sidebar: "Looking for wifi and a seat? Loc8r helps you find places to work when out and about. Perhaps with coffee, cake or a pint? Let Loc8r help you find the place you're looking for.",
locations: responseBody,
message: message
});
};

/* GET 'home' page */
module.exports.homelist = function(req, res) {
res.render('locations-list', {
title: 'Loc8r - find a place to work with wifi',
pageHeader: {
title: 'Loc8r',
strapline: 'Find places to work with wifi near you!'
},
sidebar: "Looking for wifi and a seat? Loc8r helps you find places to work when out and about. Perhaps with coffee, cake or a pint? Let Loc8r help you find the place you're looking for.",
locations: [{
name: 'Starcups',
address: '125 High Street, Reading, RG6 1PS',
rating: 3,
facilities: ['Hot drinks', 'Food', 'Premium wifi'],
distance: '100m'
}, {
name: 'Cafe Hero',
address: '125 High Street, Reading, RG6 1PS',
rating: 4,
facilities: ['Hot drinks', 'Food', 'Premium wifi'],
distance: '200m'
}, {
name: 'Burger Queen',
address: '125 High Street, Reading, RG6 1PS',
rating: 2,
facilities: ['Food', 'Premium wifi'],
distance: '250m'
}]
});
module.exports.homelist = function(req, res){
var requestOptions, path;
path = '/api/locations';
requestOptions = {
url : apiOptions.server + path,
method : "GET",
json : {},
qs : {
lng : -0.7992599,
lat : 51.378091,
maxDistance : 20
}
};
request(
requestOptions,
function(err, response, body) {
var i, data;
data = body;
if (response.statusCode === 200 && data.length) {
for (i=0; i<data.length; i++) {
data[i].distance = _formatDistance(data[i].distance);
}
}
renderHomepage(req, res, data);
}
);
};

var getLocationInfo = function (req, res, callback) {
var requestOptions, path;
path = "/api/locations/" + req.params.locationid;
requestOptions = {
url : apiOptions.server + path,
method : "GET",
json : {}
};
request(
requestOptions,
function(err, response, body) {
var data = body;
if (response.statusCode === 200) {
data.coords = {
lng : body.coords[0],
lat : body.coords[1]
};
callback(req, res, data);
} else {
_showError(req, res, response.statusCode);
}
}
);
};

var renderDetailPage = function (req, res, locDetail) {
res.render('location-info', {
title: locDetail.name,
pageHeader: {title: locDetail.name},
sidebar: {
context: 'is on Loc8r because it has accessible wifi and space to sit down with your laptop and get some work done.',
callToAction: 'If you\'ve been and you like it - or if you don\'t - please leave a review to help other people just like you.'
},
location: locDetail
});
};

/* GET 'Location info' page */
module.exports.locationInfo = function(req, res) {
res.render('location-info', {
title: 'Starcups',
pageHeader: {
title: 'Starcups'
},
sidebar: {
context: 'is on Loc8r because it has accessible wifi and space to sit down with your laptop and get some work done.',
callToAction: 'If you\'ve been and you like it - or if you don\'t - please leave a review to help other people just like you.'
},
location: {
name: 'Starcups',
address: '125 High Street, Reading, RG6 1PS',
rating: 3,
facilities: ['Hot drinks', 'Food', 'Premium wifi'],
coords: {
lat: 51.455041,
lng: -0.9690884
},
openingTimes: [{
days: 'Monday - Friday',
opening: '7:00am',
closing: '7:00pm',
closed: false
}, {
days: 'Saturday',
opening: '8:00am',
closing: '5:00pm',
closed: false
}, {
days: 'Sunday',
closed: true
}],
reviews: [{
author: 'Simon Holmes',
rating: 5,
timestamp: '16 July 2013',
reviewText: 'What a great place. I can\'t say enough good things about it.'
}, {
author: 'Charlie Chaplin',
rating: 3,
timestamp: '16 June 2013',
reviewText: 'It was okay. Coffee wasn\'t great, but the wifi was fast.'
}]
}
});
module.exports.locationInfo = function(req, res){
getLocationInfo(req, res, function(req, res, responseData) {
renderDetailPage(req, res, responseData);
});
};

var renderReviewForm = function (req, res, locDetail) {
res.render('location-review-form', {
title: 'Review ' + locDetail.name + ' on Loc8r',
pageHeader: { title: 'Review ' + locDetail.name },
error: req.query.err
});
};

/* GET 'Add review' page */
module.exports.addReview = function(req, res) {
res.render('location-review-form', {
title: 'Review Starcups on Loc8r',
pageHeader: {
title: 'Review Starcups'
},
user: {
displayName: "Simon Holmes"
module.exports.addReview = function(req, res){
getLocationInfo(req, res, function(req, res, responseData) {
renderReviewForm(req, res, responseData);
});
};

/* POST 'Add review' page */
module.exports.doAddReview = function(req, res){
var requestOptions, path, locationid, postdata;
locationid = req.params.locationid;
path = "/api/locations/" + locationid + '/reviews';
postdata = {
author: req.body.name,
rating: parseInt(req.body.rating, 10),
reviewText: req.body.review
};
requestOptions = {
url : apiOptions.server + path,
method : "POST",
json : postdata
};
if (!postdata.author || !postdata.rating || !postdata.reviewText) {
res.redirect('/location/' + locationid + '/reviews/new?err=val');
} else {
request(
requestOptions,
function(err, response, body) {
if (response.statusCode === 201) {
res.redirect('/location/' + locationid);
} else if (response.statusCode === 400 && body.name && body.name === "ValidationError" ) {
res.redirect('/location/' + locationid + '/reviews/new?err=val');
} else {
console.log(body);
_showError(req, res, response.statusCode);
}
});
}
);
}
};
5 changes: 3 additions & 2 deletions app_server/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ var ctrlOthers = require('../controllers/others');

/* Locations pages */
router.get('/', ctrlLocations.homelist);
router.get('/location', ctrlLocations.locationInfo);
router.get('/location/review/new', ctrlLocations.addReview);
router.get('/location/:locationid', ctrlLocations.locationInfo);
router.get('/location/:locationid/review/new', ctrlLocations.addReview);
router.post('/location/:locationid/review/new', ctrlLocations.doAddReview);

/* Other pages */
router.get('/about', ctrlOthers.about);
Expand Down
11 changes: 10 additions & 1 deletion app_server/views/_includes/sharedHTMLfunctions.jade
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,13 @@ mixin outputRating(rating)
- for (var i = 1; i <= rating; i++)
span.glyphicon.glyphicon-star
- for (i = rating; i < 5; i++)
span.glyphicon.glyphicon-star-empty
span.glyphicon.glyphicon-star-empty

mixin formatDate(dateString)
-var date = new Date(dateString);
-var d = date.getDate();
-var monthNames = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
-var m = monthNames[date.getMonth()];
-var y = date.getFullYear();
-var output = d + ' ' + m + ' ' + y;
=output
3 changes: 2 additions & 1 deletion app_server/views/layout.jade
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ html
small &copy; Simon Holmes 2014

script(src='/javascripts/jquery-1.11.1.min.js')
script(src='/bootstrap/js/bootstrap.min.js')
script(src='/bootstrap/js/bootstrap.min.js')
script(src='/javascripts/validation.js')
5 changes: 3 additions & 2 deletions app_server/views/location-info.jade
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ block content
.col-xs-12
.panel.panel-primary.review-panel
.panel-heading
a.btn.btn-default.pull-right(href="/location/review/new") Add review
a.btn.btn-default.pull-right(href="/location/#{location._id}/review/new") Add review
h2.panel-title Customer reviews
.panel-body.review-container
each review in location.reviews
Expand All @@ -52,7 +52,8 @@ block content
span.rating
+outputRating(review.rating)
span.reviewAuthor #{review.author}
small.reviewTimestamp #{review.timestamp}
small.reviewTimestamp
+formatDate(review.createdOn)
.col-xs-12
p !{(review.reviewText).replace(/\n/g, '<br/>')}
.col-xs-12.col-md-3
Expand Down
6 changes: 4 additions & 2 deletions app_server/views/location-review-form.jade
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ extends layout
block content
.row.page-header
.col-lg-12
h1 Review Starcups
h1= pageHeader.title
.row
.col-xs-12.col-md-6
form.form-horizontal(action="/location", method="get", role="form")
form.form-horizontal(action="", method="post", role="form")
- if (error == "val")
.alert.alert-danger(role="alert") All fields required, please try again
.form-group
label.col-xs-10.col-sm-2.control-label(for="name") Name
.col-xs-12.col-sm-10
Expand Down
3 changes: 2 additions & 1 deletion app_server/views/locations-list.jade
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ block content
small &nbsp;#{pageHeader.strapline}
.row
.col-xs-12.col-sm-8
.error= message
.row.list-group
each location in locations
.col-xs-12.list-group-item
h4
a(href="/location")= location.name
a(href="/location/#{location._id}")= location.name
small &nbsp;
+outputRating(location.rating)
span.badge.pull-right.badge-default= location.distance
Expand Down
Loading