A Web based Movie Review Community and database.
- Summary
- User Story
- Dependencies
- Installation
- Functionality
- Creators
- Roles
- Contributing
- Tests
- Questions
- License
This web application is a movie review hub for people who want to get away from the mainstream. Let’s face it… no one really likes tomatoes, especially RottenTomatoes. It can all be a bit Overrated.
As an unauthenticated user you can use the search engine, so that you can look up movies you are interested in.
As a UA you can click on buttons “add to watchlist” or write a review, so that you can be redirected to login or created an account to join the movie community.
As an authenticated user you can search for movies you have or have not seen, so that you can add movies to your watch-list or write a review.
As an authenticated user you can visit your profile, so that you can see your movie-list, movie-review list, and write a review from your list.
As an authenticated user you can use the navigation bar and click on “View Members”, so that you can see other members listed and their reviews.
As an authenticated user you can logout, so that you can end your session.
Built With
- HTML 5
- CSS
- GitHub
- JavaScript
- BootStrap
- Git
- Node
- Express
- Express-Handlebars
- MySQL
- HEROKU
- JAWSDB-MySQL
- omdbapi
package.json Dependencies
There is no installation required if you wish to access this app as is from the deployed site on Heroku.
For local installation Node.js needs to be installed as well as MySQL and MySQl Workbench.
Please clone or download the project folder. And create a new database in Workbench called "crtierion":
CREATE DATABASE criterion;
Once the database is set up locally verify that the password to access the database is updates in: config/config.son.
"development": {
"username": "root",
"password": "password",
"database": "criterion",
"host": "127.0.0.1",
"port": 3306,
"dialect": "mysql"
}
Open your prefered terminal or comand_promt program and navigate into the project folder. Run the following command:
npm install
and then run the application with the next command:
node server.js
The application will be visible in your web browser of choice at:
localhost:8080
Once you have created an account, added movies to your watchlist or written a review, go check out the tables created in the MySQL Workbench to see your captured data.
This Apllication in its development used node-express to create a local sever to host and access our PAI database by conncting to the MySQL Workbench's local port to send GET Requests, Posts, and Update the local database in out "criterion" database in Workbench.
This application also uses Axios to make GET requests to the OMDB API.
For Example: Our search bar makes a general GET request to search for movie tieles with the key word submitted from our web page client side. The request retrieves a top ten list of mvies that inclues the movie title, year released, movie rating, genre, and short plot.
When an authenticated(logged in user) interacts with the "Watchlist" button- the onClick event listeners will push the movie id, and accoiated user info a table for future reference.
When an authenticated(logged in user) interacts with the "Review" button- the onClick event listeners will push the movie id, accoiated user info, and review into the appropriate a tables for future reference.
As you can see in the code snippet below this is what is triggered by the event liseners:
$(document).ready(function () {
var button = $(".submitSearch");
button.on("click", function () {
var movieObj = [];
$(".searchResults").empty();
$.ajax({
url: `https://www.omdbapi.com/?apikey=b9e5adb0&s=${$("#searchBar").val()}`,
method: "GET"
}).then(function (response) {
console.log(response);
for (i = 0; i < response.Search.length; i++) {
queryURL = "http://www.omdbapi.com/?apikey=b9e5adb0&i=" + response.Search[i].imdbID;
$.ajax({
url: queryURL,
method: "GET"
}).then(function (res) {
if (res.Poster == "N/A") {
console.log(res.title, " doesn't have a poster");
}
else {
console.log("title search:", res);
var h2 = $("<h2>");
var h3 = $("<h3>");
var p = $("<p>");
var img = $("<img>");
var btn1 = $("<button>");
var btn2 = $("<button>");
let film = {
title: res.Title,
year: res.Year,
genre: res.Genre,
rating: res.Rated,
plot: res.Plot,
poster: res.Poster,
imdbId: res.imdbID
};
movieObj.push(film);
h2.text(res.Title + " (" + res.Year + ") ")
h3.text(res.Genre + " | " + "Rated: " + res.Rated);
p.text(res.Plot);
img.attr("src", res.Poster);
btn1.text("Watch List").attr("id", res.imdbID).attr("class", "watchList btn btn-secondary").attr("name", res.Title);
btn2.text("Seen it!").attr("id", res.imdbID).attr("class", "reviews btn btn-secondary").attr("name", res.Title).attr("data-bs-toggle", "modal").attr("data-bs-target", "#exampleModal").attr("data-bs-whatever", res.imdbID);
$(".searchResults").append(h2, h3, img, p, btn1, btn2);
}
})
}
return movieObj;
}).then(function (movieObj) {
console.log(movieObj)
});
});
$(document).on("click", ".watchList", function (event) {
event.preventDefault();
console.log("test");
let imdbID = this.id;
let name = this.name
let newMovie = {
name: name,
imdbID: imdbID
}
$.ajax({
url: "/api/movies",
method: "POST",
data: newMovie
}).then(function (response) {
console.log(response);
if (response.err) {
window.location = "/signup";
}
})
$.ajax({
url: "/api/movies",
method: "POST",
data: newMovie
}).then(function (response) {
console.log(response);
if (response.err) {
window.location = "/signup";
}
$.ajax({
url: "/api/usermovie/unseen",
method: "POST",
data: {id: newMovie.imdbID}
}).then(function (res) {
console.log(res)
})
})
});
$(document).on("click", ".reviews", function (event) {
event.preventDefault();
console.log("test");
let imdbID = this.id;
let name = this.name
let newMovie = {
name: name,
imdbID: imdbID
}
$.ajax({
url: "/api/movies",
method: "POST",
data: newMovie
}).then(function (response) {
console.log(response);
if (response.err) {
window.location = "/signup";
}
})
});
});
Using Express-Handlebars allows for the use of a single web page. Express-Handlebars requires the naming conventios of the folders "views", "layouts", and "partials".
The main.handlesbars located in the views/layouts folder has the basic HTML 5 page setup as well as BootStrap Brand Nav and a Grid System Container. Within the grid container is the handlebars tag for additional handle content to be imported into the field of {{{ body }}}.
Each web page body content is found at the base level of the views folder. Taking a look at the folder you can see a few pages listed. The reapeating sub sections of the web pages are found in the Partials/movies folder.
The reviews are rendered on the user profile using a block.handlebars segments that relies on both data being pulled in to and object from both the OMDB API and our MySQL "criterion" Database to be rendered into our handlebar tags with finesse.
router.get("/user/:profile", function (req, res) {
var hbsObject = {};
var profile = req.params.profile;
console.log(profile);
db.User.findOne({
where: {
username: profile,
},
}).then(function (userInf) {
hbsObject.userName = userInf.dataValues.username;
hbsObject.img = userInf.dataValues.imgURL;
db.UserMovie.findAll({
where: {
userID: userInf.id,
},
}).then(function (reviewInf) {
reviewArr = [];
for (i = 0; i < reviewInf.length; i++) {
reviewArr.push(reviewInf[i].dataValues);
}
hbsObject.reviews = reviewArr;
var promiseArr = [];
for (let i = 0; i < reviewInf.length; i++) {
promiseArr.push(
db.Movie.findOne({
where: {
ID: reviewInf[i].dataValues.movieID,
},
}).then(function (results) {
// console.log("movie database ========================", "\n", results.dataValues)
console.log("===============================", "\n", reviewInf[i]);
var movieData = {
movieID: reviewInf[i].dataValues.movieID,
review: reviewInf[i].dataValues.review,
rating: reviewInf[i].dataValues.rating,
watched: reviewInf[i].dataValues.watched,
};
return axios
.get(
"http://www.omdbapi.com/?apikey=b9e5adb0&i=" +
results.dataValues.imdbID
)
.then(function (response) {
movieData.data = response.data;
return movieData;
});
})
);
}
Promise.all(promiseArr).then(function (responses) {
hbsObject.movies = responses;
hbsObject = {
movies: hbsObject.movies,
username: hbsObject.userName,
avatar: hbsObject.img,
};
console.log("Handlebars Object:", hbsObject);
res.render("profile", hbsObject);
});
});
});
});
Spencer
Sammy K
& Gloria C Varela
let all = [
ideation:"decide what we are going to make";
proposal:"work together to fill out";
Delegation:"assign roles and tasks for individual";
Database:"discuss data table planning";
schedule:"working out of class, meetings";
stuck-time:"10-15 min, help each other";
free-time:"help other team members";
gitHub:"create branches, pull requests, approve";
Merging:"communicate before,during, and after merging";
];
let spencer = [
Passport:"enable login and out, restrict UA users";
Bcrypt:"utilize for password storage";
omdbapi:"append search results, push to database";
Models:"index.js, user.js, usermovie.js";
client:"public/index.js";
Config:"database link, middleware, passport.js";
Routing:"html and api";
];
let sammy = [
Models:"index.js, movies.js, user.js, usermovie.js";
client:"public/index.js, ";
Routing:"api, our database and omdbapi/IMDB";
block.handlebars:"backend retrieval-axios/client";
Server-side:"pivot client res to server res ";
Handlebars:"trouble-shoot transition into handlebars";
];
let gloria = [
wireFrames:"adobe-illustrator";
css:"custom styling classes and ids";
bootStrap:"all responsive grid systems layouts";
.handlebars:"front end main pages content";
block.handlebars:"front end repeating template";
stars-rating:"html/css layout, animation";
anime.js:"look for animation ideas for wow factor";
Miscellaneous:"google-slides, ReadMe.md";
];
// There are no contributions at this time
// There is no test at this time
If you have any questions contact: Any of the Creators