diff --git a/.env b/.env new file mode 100644 index 0000000..1cc5897 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +SALT_ROUNDS=12 +APP_SECRET=supersecretkey \ No newline at end of file diff --git a/app.js b/app.js index 111ec29..c75b69e 100644 --- a/app.js +++ b/app.js @@ -2,6 +2,8 @@ const app = require('express')() const bodyParser = require('body-parser') const cors = require('cors') const logger = require('morgan') +const path = require('path') + const AppRouter = require('./routes/AppRouter') @@ -14,4 +16,13 @@ app.use(bodyParser.urlencoded({ extended: true })) app.get('/', (req, res) => res.json({ message: 'Server Works' })) app.use('/api', AppRouter) + +if (process.env.NODE_ENV === 'production') { + app.use(express.static(path.join(__dirname, 'client/build'))) + app.get('*', (req, res) => { + res.sendFile(path.join(`${__dirname}/client/build/index.html`)) + }) +} + + app.listen(PORT, () => console.log(`Server Started On Port: ${PORT}`)) diff --git a/client/src/App.js b/client/src/App.js index 4760517..51f4a29 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,5 +1,4 @@ import './styles/App.css' -import './styles/RazaAbout.css' import './styles/JinHome.css' import './styles/Sam.css' import React, { useState, useEffect } from 'react' @@ -70,7 +69,7 @@ function App() { { games.map(game => ( - } /> + } /> )) } diff --git a/client/src/components/ReviewCard.jsx b/client/src/components/ReviewCard.jsx index 7eaf4aa..5b9dad4 100644 --- a/client/src/components/ReviewCard.jsx +++ b/client/src/components/ReviewCard.jsx @@ -2,7 +2,7 @@ import React from 'react' import swal from '@sweetalert/with-react' import {DeleteReview } from '../services/ReviewServices' -const ReviewCard = ({review}) => { +const ReviewCard = ({review, user}) => { const handleDeleteReview = async () => { await DeleteReview(review.id) @@ -12,12 +12,12 @@ const ReviewCard = ({review}) => { return (
-

Reviewer:

{review.User.name}

-

{review.content}

+

{review.User.name}:

+

{review.content}

- {(review.User.id === review.user_id) &&
+ {(review.User.id === review.user_id) && -
} + }
) } diff --git a/client/src/pages/GameDetails.js b/client/src/pages/GameDetails.js index 3c92e2c..dd74a84 100644 --- a/client/src/pages/GameDetails.js +++ b/client/src/pages/GameDetails.js @@ -5,7 +5,7 @@ import ReviewCard from "../components/ReviewCard"; import SubmitReviewForm from "../components/SubmitReviewForm"; import swal from '@sweetalert/with-react' -const GameDetails = ({game, user}) => { +const GameDetails = ({game, user, authenticated}) => { const [cart, setCart] = useState({}) const [gameReviews, setGameReviews] = useState([]) const [reviewButton, toggleReviewButton] = useState(false) @@ -35,7 +35,7 @@ const GameDetails = ({game, user}) => { } const reviewsExist = ( -

Reviews:

+

Reviews:

) useEffect(() => { if (user) findCart() @@ -54,7 +54,8 @@ const GameDetails = ({game, user}) => {

Platform: {game.platform}

Description: {game.description}

- +
+ {(user && authenticated) && } {reviewButton && } diff --git a/client/src/services/api.js b/client/src/services/api.js index 9138fa8..dd8f8e9 100644 --- a/client/src/services/api.js +++ b/client/src/services/api.js @@ -1,6 +1,9 @@ import Axios from 'axios' -export const BASE_URL = 'http://localhost:3001/api' +export const BASE_URL = process.env.NODE_ENV === 'production' + ? `${window.location.origin}/api` + : 'http://localhost:3001/api' + const Client = Axios.create({ baseURL: BASE_URL }) // Intercepts every request axios makes diff --git a/client/src/styles/App.css b/client/src/styles/App.css index 4c2d274..a2caf14 100644 --- a/client/src/styles/App.css +++ b/client/src/styles/App.css @@ -2,13 +2,6 @@ display: flex; } -.popular-games { - -} - -.recent-games { - -} .game-card { max-width: 250px; @@ -41,3 +34,430 @@ p { color: white; } + +@import url('https://fonts.googleapis.com/css2?family=Permanent+Marker&display=swap'); + +/* applies to all elements */ +* { + text-align: center; + box-sizing: border-box; + font-family: Roboto; +} +/* body styles */ +body { + background: linear-gradient(#16222a, #3a6073); + background-position: center center; + background-size: cover; + width: 100%; + height: 100vh; + background-color: transparent; + background-repeat: no-repeat; + background-size: 1000% 1000%; + position: relative; + overflow-x: hidden; + margin: 0; +} + +/* NavBar styles */ +header { + background-color: #000000; + width: 100%; +} +a { + text-decoration: none; + font-weight: bold; + font-size: 25px; + color: white; +} +button { + font-size: 20px; + font-weight: bold; +} + +.top-nav { + display: flex; + justify-content: space-between; + width: 100%; +} +.right-top-nav { + margin-top: 1%; + display: flex; + width: auto; +} +.right-top-nav button { + width: 5em; + height: 2em; + margin: 0 5px; + border-radius: 12.5px; +} +.right-top-nav a { + width: 5em; + height: 2em; + margin: 0 5px; + border-radius: 12.5px; + padding: 0.5em; +} + +.sign-but { + background-color: #f37971; + color: white; +} +.sign-but:hover { + background-color: white; + color: #f37971; +} + +.log-but { + background-color: #01c3cc; + color: white; +} +.log-but:hover { + background-color: white; + color: #01c3cc; +} + +.bottom-nav { + width: 100%; + margin: auto; + padding-bottom: 1em; +} +.right-bottom-nav { + width: 100%; + margin-top: -6em; + margin-bottom: 2em; +} +.right-bottom-nav a { + margin: 4%; + padding: 0.5em; + border-radius: 12.5px; +} +.right-bottom-nav a:hover { + background-color: #222222; +} +.search-form { + width: 40%; + height: auto; + margin: auto; +} +.search-button { + width: 5em; + height: 2.5em; + margin: 0 10px; + background-color: #01c3cc; + color: white; + border-radius: 30px; +} +.search-button:hover { + background-color: white; + color: #01c3cc; +} + +.search-input { + font-size: 20px; + height: 2.5em; + width: 80%; + border-radius: 30px; +} +.search-input:focus { + border: 4px #01c3cc solid; +} + + +/* homepage styling */ +.home-cont { + margin-top: 3em; +} + +.home-games { + display: flex; +} + +.games-cont{ + display: grid; + grid-template: auto / repeat(2, 1fr); +} + +.recent-games, .popular-games { + padding: 1em 2em; + border: 4px solid silver; + border-radius: 20px; +} +.game-card { + max-width: 250px; + max-height: 300px; + border-top-left-radius : 30px; + border-bottom-right-radius : 30px; + background-color: #1b1b1b; + cursor: pointer; + transition: all 0.2s; + margin: 2em; + overflow-x: auto; + overflow-y: auto; +} +.game-card:hover { + opacity: 0.6; +} + +.game-card img { + width: 100%; + border-top-left-radius : 30px; +} + +.hover-info > h3, +p { + color: white; + margin: 0em; + font-weight: bold; +} +.hover-info > h3 { + margin-top: -0.5em; +} +.add-button, .add-cart { + background-color: #01c3cc; + color: white; + width: auto; + height: 1.7em; + border-radius: 12.5px; +} +.add-button:hover, .add-cart:hover { + background-color: white; + color: #01c3cc; +} + +/* games page styling */ +.games { + width: 80%; + display: grid; + grid-template: auto / repeat(5, 1fr); + margin: auto +} + +/* games page styling */ +.search-results { + width: 80%; + display: grid; + grid-template: auto / repeat(5, 1fr); + margin: auto; +} + +/* about page styling */ +.about-h1 { + color: white; + font-family: 'Permanent Marker', cursive; + margin-top: 0.5em +} +.about-us-container { + margin-top: -3em; + display: flex; + justify-content: space-around; +} +.about-card { + background-color: darkgray; + border-radius: 10px; + padding-bottom: 20px; + margin: 100px; +} +.card-margin { + margin-bottom: 50px; +} + +.about-card > h2 { + margin-top: 0.2em; + text-align: center; + font-family: 'Permanent Marker', cursive; +} + +.image-div > img { + height: 30vh; +} +a:link { + text-decoration: none; + color: white; +} +a:visited { + color: white; +} +.about-card a { + text-align: center; + font-size: 25px; + font-weight: bold; + display: block; + margin: -0.3em auto; +} +.links { + text-align: center; +} +.Team { + display: flex; + width: 50%; + height: 550px; + margin: auto; + margin-top: -4em; + justify-content: center; +} + +/* gameDetails styling */ + +.top-half { + display: flex; + width: 90%; + margin: 2em auto; + border: 4px solid silver; + border-radius: 20px; + padding: 2em +} +.top-half div { + width:50%; + margin: auto 1em; + border-radius: 20px +} + .top-half div > img{ + width: 100%; + border-radius: 20px + } +.right-side { + width: 50%; + margin: auto 1em; + padding: auto 1em; + border-radius: 20px; +} +.right-side * { + margin: 0.5em auto; + font-size: 18px; +} +.right-side h1{ + font-size: 40px; + color: #f37971; + font-weight: bold; +} + +.show-review-form { + background-color: #f37971; + color: white; + width: auto; + height: 1.7em; + border-radius: 12.5px; + display: inline; +} +.show-review-form:hover{ + background-color: white; + color:#f37971; +} + +/* review section styling */ +.reviews-cont { + width: 70%; + margin: auto; +} + +.review-card { + border: 1px solid white; + border-radius: 30px; + background-color: rgb(65, 63, 63); + height: 40px; + padding: 2em auto; + margin: 0.6em auto; + +} + +.review-card p, h4 { + display: inline-block; + margin: auto 0.4em; + font-size: 22px; + font-weight: bold; +} + +.review-card p{ + color: #01c3cc; +} +.review-card h4{ + color: white; +} + +.delete-review { + background-color: #f37971; + color: white; + width: auto; + height: 1.7em; + border-radius: 12.5px; + margin: auto 1em; + display: inline; +} +.delete-review:hover { + background-color: white; + color:#f37971 +} + +.review-h2 { + font-size: 40px; + color: #01c3cc; + font-weight: bold; + margin-bottom: 0.5em; +} + + + + + +.home-games { + display: inline; + justify-content: space-around; +} +.home-games h1 { + color: rgb(245, 240, 240); + font-family: 'Permanent Marker', cursive; +} + +#image { + border-radius: 10px; +} + +.item-card { + max-width: 280px; + max-height: 400px; + border-radius: 4px; + background-color: #1b1b1b; + cursor: pointer; + transition: all 0.2s; + margin: 1em; +} +.item-card:hover { + opacity: 0.6; +} + +.item-card .img-wrapper { + width: auto; +} + +.item-card img { + width: 100%; + height: 200px; +} + +.item-card .hover-info { + padding: 1em; +} + +.hover-info > h3, +p { + color: white; +} + +.cart-cont { + max-width: 300px; +} + +.cart-text { + color: white; +} + +.account-page > p { + font-size: 40px; + margin: 5px; +} + +.account-page > img { + max-width: 300px; + max-height: 300px; +} + diff --git a/client/src/styles/Sam.css b/client/src/styles/Sam.css index 7a521cb..252db0c 100644 --- a/client/src/styles/Sam.css +++ b/client/src/styles/Sam.css @@ -8,10 +8,17 @@ } /* body styles */ body { - background-color: #222222; - margin: 0; - height: 100%; + background: linear-gradient(#16222a, #3a6073); + background-position: center center; + background-size: cover; + width: 100%; + height: 100vh; + background-color: transparent; + background-repeat: no-repeat; + background-size: 1000% 1000%; + position: relative; overflow-x: hidden; + margin: 0; } /* NavBar styles */ @@ -277,6 +284,15 @@ a:visited { padding: auto 1em; border-radius: 20px; } +.right-side * { + margin: 0.5em auto; + font-size: 18px; +} +.right-side h1{ + font-size: 40px; + color: #f37971; + font-weight: bold; +} .show-review-form { background-color: #f37971; @@ -284,14 +300,62 @@ a:visited { width: auto; height: 1.7em; border-radius: 12.5px; + display: inline; } .show-review-form:hover{ background-color: white; - color:#f37971 + color:#f37971; } /* review section styling */ .reviews-cont { - width: 70% + width: 70%; + margin: auto; +} + +.review-card { + border: 1px solid white; + border-radius: 30px; + background-color: rgb(65, 63, 63); + height: 40px; + padding: 2em auto; + margin: 0.6em auto; + +} + +.review-card p, h4 { + display: inline-block; + margin: auto 0.4em; + font-size: 22px; + font-weight: bold; +} + +.review-card p{ + color: #01c3cc; +} +.review-card h4{ + color: white; } +.delete-review { + background-color: #f37971; + color: white; + width: auto; + height: 1.7em; + border-radius: 12.5px; + margin: auto 1em; + display: inline; +} +.delete-review:hover { + background-color: white; + color:#f37971 +} + +.review-h2 { + font-size: 40px; + color: #01c3cc; + font-weight: bold; + margin-bottom: 0.5em; +} + + diff --git a/config/config.js b/config/config.js new file mode 100644 index 0000000..6907310 --- /dev/null +++ b/config/config.js @@ -0,0 +1,22 @@ +require('dotenv').config() + +module.exports = { + development: { + database: 'gameStart_development', + dialect: 'postgres' + }, + test: { + database: 'gameStart_test', + dialect: 'postgres' + }, + production: { + use_env_variable: 'DATABASE_URL', + dialect: 'postgres', + dialectOptions: { + ssl: { + rejectUnauthorized: false, + require: true + } + } + } +} \ No newline at end of file diff --git a/config/config.json b/config/config.json deleted file mode 100644 index f4fd3ef..0000000 --- a/config/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "development": { - "database": "gameStart_development", - "host": "127.0.0.1", - "dialect": "postgres" - }, - "test": { - "database": "gameStart_test", - "host": "127.0.0.1", - "dialect": "postgres" - }, - "production": { - "database": "gameStart_production", - "host": "127.0.0.1", - "dialect": "postgres" - } -} diff --git a/controllers/CartController.js b/controllers/CartController.js index f895851..3ad93d8 100644 --- a/controllers/CartController.js +++ b/controllers/CartController.js @@ -7,10 +7,6 @@ const GetCartItems = async (req, res) => { where: {user_id: req.params.user_id}, include: {model: Game, as: 'cart', through: {attributes: []} } }) - // const cart_items = await Cart_game.findAll({ - // where: {cart_id: cart.id}, - // include: [{model: Game, as: 'cart_items', attributes: []}] - // }) res.send(cart) } catch (error) { throw error diff --git a/middleware/index.js b/middleware/index.js index bc452ba..9b0041c 100644 --- a/middleware/index.js +++ b/middleware/index.js @@ -1,7 +1,7 @@ const bcrypt = require('bcrypt') const jwt = require('jsonwebtoken') -const SALT_ROUNDS = 12 -const APP_SECRET = 'supersecretkey' +const SALT_ROUNDS = parseInt(process.env.SALT_ROUNDS) //parsing because the env variable comes as a string but we want a number +const APP_SECRET = process.env.APP_SECRET const hashPassword = async (password) => { // Accepts a password from the request body diff --git a/models/index.js b/models/index.js index 33f09e7..4078c6c 100644 --- a/models/index.js +++ b/models/index.js @@ -5,7 +5,8 @@ const path = require('path'); const Sequelize = require('sequelize'); const basename = path.basename(__filename); const env = process.env.NODE_ENV || 'development'; -const config = require(__dirname + '/../config/config.json')[env]; +const config = require(__dirname + '/../config/config.js')[env] + const db = {}; let sequelize; diff --git a/package.json b/package.json index 2079d08..29722ff 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "nodemon app.js", "start": "node app.js", - "build": "cd client && rm -rf build && npm install && npm run build" + "build": "npm install && npx sequelize-cli db:migrate && cd client && rm -rf build && npm install && npm run build" + }, "repository": { "type": "git",