CSS hookups added and docker-compose compatibility changes made
This commit is contained in:
@@ -1,14 +1,25 @@
|
|||||||
version: '3.9'
|
version: '3.9'
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
# To Give the container a project related name run: #
|
||||||
|
# #
|
||||||
|
# docker-compose -p final-project up #
|
||||||
|
# #
|
||||||
|
# ⚠️ Make sure current directory is: /ProjectSourceCode ⚠️ #
|
||||||
|
############################################################
|
||||||
|
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
|
container_name: postgres-db
|
||||||
image: postgres:14
|
image: postgres:14
|
||||||
env_file: .env
|
env_file: .env
|
||||||
ports:
|
ports:
|
||||||
- '5433:5433'
|
- '5432:5432'
|
||||||
volumes:
|
volumes:
|
||||||
- group-project:/var/lib/postgresql/data
|
- group-project:/var/lib/postgresql/data
|
||||||
- ./src/init_data:/docker-entrypoint-initdb.d
|
- ./src/init_data:/docker-entrypoint-initdb.d
|
||||||
web:
|
web:
|
||||||
|
container_name: node-web-interface
|
||||||
image: node:lts
|
image: node:lts
|
||||||
user: 'node'
|
user: 'node'
|
||||||
working_dir: /home/node/app
|
working_dir: /home/node/app
|
||||||
@@ -18,7 +29,7 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
ports:
|
ports:
|
||||||
- '3001:3001'
|
- '3000:3000'
|
||||||
volumes:
|
volumes:
|
||||||
- ./src:/home/node/app
|
- ./src:/home/node/app
|
||||||
command: 'npm start'
|
command: 'npm start'
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const hbs = handlebars.create({
|
|||||||
// database configuration
|
// database configuration
|
||||||
const dbConfig = {
|
const dbConfig = {
|
||||||
host: 'db', // the database server
|
host: 'db', // the database server
|
||||||
port: 5433, // the database port
|
port: 5432, // the database port
|
||||||
database: process.env.POSTGRES_DB, // the database name
|
database: process.env.POSTGRES_DB, // the database name
|
||||||
user: process.env.POSTGRES_USER, // the user account to connect with
|
user: process.env.POSTGRES_USER, // the user account to connect with
|
||||||
password: process.env.POSTGRES_PASSWORD, // the password of the user account
|
password: process.env.POSTGRES_PASSWORD, // the password of the user account
|
||||||
@@ -71,13 +71,94 @@ app.use(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Serve static files from the 'public' directory
|
// Serve static files from the 'public' directory
|
||||||
app.use(express.static(path.join(__dirname, 'public')));
|
app.use(express.static(path.join(__dirname, 'resources')));
|
||||||
|
|
||||||
// *****************************************************
|
// *****************************************************
|
||||||
// <!-- Section 4 : API Routes -->
|
// <!-- Section 4 : API Routes -->
|
||||||
// *****************************************************
|
// *****************************************************
|
||||||
|
|
||||||
// TODO - Include your API routes here
|
/************************
|
||||||
|
Login Page Routes
|
||||||
|
*************************/
|
||||||
|
|
||||||
|
// Redirect to the /login endpoint
|
||||||
|
app.get('/', (req, res) => {
|
||||||
|
res.redirect('/login');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Render login page for /login route
|
||||||
|
app.get('/login', (req, res) => {
|
||||||
|
res.render('pages/login');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trigger login form to check database for matching username and password
|
||||||
|
app.post('/login', async (req, res) => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Check if username exists in DB
|
||||||
|
const user = await db.oneOrNone('SELECT * FROM users WHERE username = $1', req.body.username);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
// Redirect user to login screen if no user is found with the provided username
|
||||||
|
return res.redirect('/register');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if password from request matches with password in DB
|
||||||
|
const match = await bcrypt.compare(req.body.password, user.password);
|
||||||
|
|
||||||
|
// Check if mathc returns no data
|
||||||
|
if (!match) {
|
||||||
|
// Render the login page with the message parameter
|
||||||
|
return res.render('pages/login', { message: 'Password does not match' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save user information in the session variable
|
||||||
|
req.session.user = user;
|
||||||
|
req.session.save();
|
||||||
|
|
||||||
|
// Redirect user to the home page
|
||||||
|
res.redirect('/home');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
// Direct user to login screen if no user is found with matching password
|
||||||
|
res.redirect('/register');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/************************
|
||||||
|
Registration Page Routes
|
||||||
|
*************************/
|
||||||
|
|
||||||
|
// Render registration page for /register route
|
||||||
|
app.get('/register', (req, res) => {
|
||||||
|
res.render('pages/register');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trigger Registration Form to Post
|
||||||
|
app.post('/register', async (req, res) => {
|
||||||
|
try {
|
||||||
|
// Hash the password using bcrypt library
|
||||||
|
const hash = await bcrypt.hash(req.body.password, 10);
|
||||||
|
|
||||||
|
// Insert username and hashed password into the 'users' table
|
||||||
|
await db.none('INSERT INTO users (username, password) VALUES ($1, $2)', [req.body.username, hash]);
|
||||||
|
|
||||||
|
// Direct user to login screen after data has been inserted successfully
|
||||||
|
res.redirect('/login');
|
||||||
|
} catch (error) {
|
||||||
|
// If the insert fails, redirect to GET /register route
|
||||||
|
res.redirect('/register');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/************************
|
||||||
|
Discover Page Routes
|
||||||
|
*************************/
|
||||||
|
|
||||||
|
// Render registration page for /register route
|
||||||
|
app.get('/home', (req, res) => {
|
||||||
|
res.render('pages/home');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// *****************************************************
|
// *****************************************************
|
||||||
|
|||||||
3
ProjectSourceCode/src/resources/css/home-screen.css
Normal file
3
ProjectSourceCode/src/resources/css/home-screen.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.card-container {
|
||||||
|
margin-bottom: 35px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/* Styling to center login page items */
|
||||||
|
.login-page {
|
||||||
|
height: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center; /* Center items horizontally */
|
||||||
|
align-items: center; /* Center items vertically */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styling to center register page items */
|
||||||
|
.register-page {
|
||||||
|
height: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center; /* Center items horizontally */
|
||||||
|
align-items: center; /* Center items vertically */
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" class="h-100">
|
||||||
|
|
||||||
|
<!-- TODO: Add the head.hbs partial here -->
|
||||||
|
{{> head}}
|
||||||
|
|
||||||
|
|
||||||
|
<!-- TODO: Add the nav.hbs partial here -->
|
||||||
|
{{> nav}}
|
||||||
|
|
||||||
|
|
||||||
|
{{{body}}}
|
||||||
|
|
||||||
|
|
||||||
|
<!-- TODO: Add the footer.hbs partial here -->
|
||||||
|
{{> footer}}
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<body>
|
||||||
|
<div class="container mt-5">
|
||||||
|
<h1 class="mb-4">Discover Events</h1>
|
||||||
|
<div class="card-container">
|
||||||
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-4 g-4">
|
||||||
|
|
||||||
|
<!-- Event 1 -->
|
||||||
|
{{> event_card imageURL="https://via.placeholder.com/300" eventName="Event Name" eventDateTime="Date and Time"}}
|
||||||
|
|
||||||
|
<!-- Event 2 -->
|
||||||
|
{{> event_card imageURL="https://via.placeholder.com/300" eventName="Event Name" eventDateTime="Date and Time"}}
|
||||||
|
|
||||||
|
<!-- Event 3 -->
|
||||||
|
{{> event_card imageURL="https://via.placeholder.com/300" eventName="Event Name" eventDateTime="Date and Time"}}
|
||||||
|
|
||||||
|
<!-- Event 4 -->
|
||||||
|
{{> event_card imageURL="https://via.placeholder.com/300" eventName="Event Name" eventDateTime="Date and Time"}}
|
||||||
|
|
||||||
|
<!-- Event 5 -->
|
||||||
|
{{> event_card imageURL="https://via.placeholder.com/300" eventName="Event Name" eventDateTime="Date and Time"}}
|
||||||
|
|
||||||
|
<!-- Event 6 -->
|
||||||
|
{{> event_card imageURL="https://via.placeholder.com/300" eventName="Event Name" eventDateTime="Date and Time"}}
|
||||||
|
|
||||||
|
<!-- Event 7 -->
|
||||||
|
{{> event_card imageURL="https://via.placeholder.com/300" eventName="Event Name" eventDateTime="Date and Time"}}
|
||||||
|
|
||||||
|
<!-- Event 8 -->
|
||||||
|
{{> event_card imageURL="https://via.placeholder.com/300" eventName="Event Name" eventDateTime="Date and Time"}}
|
||||||
|
|
||||||
|
<!-- Event 9 -->
|
||||||
|
{{> event_card imageURL="https://via.placeholder.com/300" eventName="Event Name" eventDateTime="Date and Time"}}
|
||||||
|
|
||||||
|
<!-- Event 10 -->
|
||||||
|
{{> event_card imageURL="https://via.placeholder.com/300" eventName="Event Name" eventDateTime="Date and Time"}}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<body class="container">
|
||||||
|
<!-- Linking forms.css -->
|
||||||
|
<div class="login-page">
|
||||||
|
<div class="form-container">
|
||||||
|
<h1 class="mt-5 mb-4">Login</h1>
|
||||||
|
|
||||||
|
<!-- Check if message variable is present to display message partial -->
|
||||||
|
{{#if message}}
|
||||||
|
{{> message}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<form action="/login" method="POST" class="mt-3">
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="username" class="form-label">Username:</label>
|
||||||
|
<input type="text" class="form-control" id="username" name="username" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="password" class="form-label">Password:</label>
|
||||||
|
<input type="password" class="form-control" id="password" name="password" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary">Submit</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p class="mt-3">Don't have an account? <a href="/register">Register</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<body class="container">
|
||||||
|
<div class="register-page">
|
||||||
|
<div class="form-container">
|
||||||
|
<h1 class="mt-5 mb-4">Register</h1>
|
||||||
|
|
||||||
|
<form action="/register" method="POST" class="mt-3">
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="username" class="form-label">Username:</label>
|
||||||
|
<input type="text" class="form-control" id="username" name="username" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="password" class="form-label">Password:</label>
|
||||||
|
<input type="password" class="form-control" id="password" name="password" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p class="mt-3">Already have an account? <a href="/login">Login</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|||||||
10
ProjectSourceCode/src/views/partials/event_card.hbs
Normal file
10
ProjectSourceCode/src/views/partials/event_card.hbs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<div class="col-md-4 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<img src="{{imageURL}}" class="card-img-top" alt="Event Image">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">{{eventName}}</h5>
|
||||||
|
<p class="card-text">Date and Time: {{eventDateTime}}</p>
|
||||||
|
<a href="#" class="btn btn-primary">Book Now</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<footer class="text-center text-muted w-100 mt-auto fixed-bottom">
|
||||||
|
<p>
|
||||||
|
© 2024 - CSCI 3308 Group 6
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- TODO: Add the <script><script /> tag to include bootstrap javascript -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
</footer>
|
||||||
|
|||||||
17
ProjectSourceCode/src/views/partials/head.hbs
Normal file
17
ProjectSourceCode/src/views/partials/head.hbs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
|
||||||
|
<meta name="description" content="" />
|
||||||
|
|
||||||
|
<!-- Linking forms.css -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="css/login_and_registration.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href="css/home-screen.css">
|
||||||
|
|
||||||
|
<!-- TODO: Include the `title` partial here -->
|
||||||
|
{{> title}}
|
||||||
|
|
||||||
|
<!-- Include Bootstrap CSS -->
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
|
<body class="h-100 d-flex flex-column"></body>
|
||||||
|
</head>
|
||||||
|
|
||||||
5
ProjectSourceCode/src/views/partials/message.hbs
Normal file
5
ProjectSourceCode/src/views/partials/message.hbs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{{#if message}}
|
||||||
|
<div class="alert alert-{{#if error}}danger{{else}}success{{/if}}" role="alert">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
27
ProjectSourceCode/src/views/partials/nav.hbs
Normal file
27
ProjectSourceCode/src/views/partials/nav.hbs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
<nav class="navbar navbar-expand-sm border-bottom">
|
||||||
|
<div class="container">
|
||||||
|
<button
|
||||||
|
class="navbar-toggler ms-auto"
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="collapse"
|
||||||
|
data-bs-target="#navbar-collapse"
|
||||||
|
aria-controls="navbar"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbar-collapse">
|
||||||
|
<ul class="navbar-nav me-auto">
|
||||||
|
<li class="nav-item">
|
||||||
|
<!-- TODO: For Discover, add a <a> tag with an attribute href to call the '/discover' API -->
|
||||||
|
<a class="nav-link" href="/discover">Discover</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="nav-item me-1">
|
||||||
|
<!-- TODO: For Logout, add a <a> tag with an attribute href to call the '/logout API -->
|
||||||
|
<a class="nav-link" href="/logout">Logout</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
5
ProjectSourceCode/src/views/partials/title.hbs
Normal file
5
ProjectSourceCode/src/views/partials/title.hbs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{{#if first_name}}
|
||||||
|
<title> {{first_name}} - CSCI 3308 Lab 8 </title>
|
||||||
|
{{else}}
|
||||||
|
<title> CSCI 3308 Lab 8 </title>
|
||||||
|
{{/if}}
|
||||||
Reference in New Issue
Block a user