-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #34 from BrockAltug/feature
Feature
- Loading branch information
Showing
187 changed files
with
5,931 additions
and
11,907 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,91 @@ | ||
# Module 14 Mini-Project: Crowdfunding App | ||
|
||
In this mini-project, you will work with a group to build a full-stack crowdfunding app using Node.js, Express.js, Sequelize, Handlebars.js, and MVC architecture. | ||
|
||
## User Stories | ||
|
||
* As a user, I want to see a list of current projects seeking funding. | ||
|
||
* As a user, I want to be able to create an account. | ||
|
||
* As a registered user, I want to post my own projects to ask for funding. | ||
|
||
### Acceptance Criteria | ||
|
||
* It's done when the `/` homepage route renders a list of all projects from the database. | ||
|
||
* It's done when the `/project/:id` route renders an individual project's details based on the route parameter id. | ||
|
||
* It's done when the `/login` route renders a form to log in and a form to create a new account. | ||
|
||
* It's done when an existing user can enter their credentials on the login page to create a session on the server. | ||
|
||
* It's done when a new user can create an account on the login page and then be immediately logged in with a session. | ||
|
||
* It's done when the `/profile` route renders the logged-in user's projects and a form to create a new project. | ||
|
||
* It's done when only a logged in user can visit the `/profile` route. | ||
|
||
* It's done when a logged in user is redirected to `/profile` when they try to visit `/login` again. | ||
|
||
* It's done when a user on the profile page can use the form to create a new project in the database. | ||
|
||
* It's done when a user on the profile page can select a "Delete" button to remove their project from the database. | ||
|
||
* It's done when a logged-in user can select a "Logout" button to remove their session. | ||
|
||
* It's done when the session for a logged-in user expires after a set time. | ||
|
||
* It's done when the API routes to create and delete posts are protected from non logged-in users. | ||
|
||
* It's done when the code is organized using MVC architecture. | ||
|
||
* It's done when the views are rendered with Handlebars.js templates. | ||
|
||
## Specifications | ||
|
||
* The database models have the following fields and associations: | ||
|
||
* `User` | ||
|
||
* `id`: primary key | ||
|
||
* `name` | ||
|
||
* `email` | ||
|
||
* `password` | ||
|
||
* `Project` | ||
|
||
* `id`: primary key | ||
|
||
* `name` | ||
|
||
* `description` | ||
|
||
* `date_created` | ||
|
||
* `needed_funding` | ||
|
||
* `user_id`: foreign key that references `User.id` | ||
|
||
* Users have many projects, and projects belong to a user. | ||
|
||
* If a user is deleted, all associated projects are also deleted. | ||
|
||
--- | ||
|
||
## Getting Started | ||
|
||
The following should be created for the Mini-Project: | ||
|
||
* Be sure to change the `.env.EXAMPLE` file to just `.env` and update the credentials correctly. | ||
|
||
* Create a `Views` folder to setup the folder structure to follow the MVC paradigm. | ||
|
||
* Be sure to review over the [Express Handlebars](https://www.npmjs.com/package/express-handlebars) if you need a refresher on how to set up Handlebars for your `Views` folder. | ||
|
||
* Consider the task based on the Acceptance Criteria. Which folder should you work to see data returning from an API call? | ||
|
||
## 💡 Hints | ||
|
||
* What tools can you use to test the existing API routes if you don't yet have a front end? | ||
|
||
* Where would you place the client-side JavaScript for capturing form data? | ||
|
||
* How can middleware help protect routes from non logged-in users? | ||
|
||
* How can Handlebars.js helpers (both built-in and custom) be used to render the desired results? | ||
|
||
## 🏆 Bonus | ||
|
||
If you have completed this activity, work through the following challenge with your partner to further your knowledge: | ||
|
||
* Add an `/edit/:id` route for logged in users to update their projects' details. Then deploy the app to Render! | ||
|
||
--- | ||
© 2024 edX Boot Camps LLC. Confidential and Proprietary. All Rights Reserved. | ||
# MVC Mini Project | ||
|
||
## Concepts Covered | ||
|
||
### **1. Authentication** | ||
|
||
- Implemented user login and signup functionalities. | ||
- Used session storage to maintain user sessions with `express-session` and `connect-session-sequelize`. | ||
- Redirected unauthenticated users to the login page using a custom `withAuth` middleware. | ||
|
||
### **2. Models** | ||
|
||
- **User Model**: | ||
- Stores user information (e.g., name, email, password). | ||
- Includes password hashing with bcrypt during user creation and updates. | ||
- Provides a `checkPassword` method for authentication. | ||
- **Project Model**: | ||
- Stores project details such as name, description, funding required, and creation date. | ||
- Associated with the `User` model for relational data management. | ||
|
||
### **3. Routes** | ||
|
||
- **User Routes**: | ||
- `POST /api/users`: Handles user registration. | ||
- `POST /api/users/login`: Handles user login. | ||
- `POST /api/users/logout`: Handles user logout. | ||
- **Project Routes**: | ||
- `POST /api/projects`: Allows logged-in users to create a new project. | ||
- `DELETE /api/projects/:id`: Allows logged-in users to delete a project they created. | ||
- **Home Routes**: | ||
- `GET /`: Renders the homepage with a list of projects. | ||
- `GET /project/:id`: Displays details for a specific project. | ||
- `GET /profile`: Displays the user's profile and their projects (protected route). | ||
|
||
### **4. Views** | ||
|
||
- **Homepage**: | ||
- Displays a list of projects, including funding requirements, creators, and creation dates. | ||
- Utilizes Handlebars.js to dynamically render project data. | ||
- **Profile Page**: | ||
- Allows users to view and manage their created projects. | ||
- Provides options to add new projects or delete existing ones. | ||
- **Login Page**: | ||
- Enables users to log in or create an account. | ||
|
||
### **5. Helpers** | ||
|
||
- Custom Handlebars helpers: | ||
- `get_emoji`: Dynamically renders emoji based on certain conditions. | ||
- `format_amount`: Formats numbers (e.g., funding required). | ||
- `format_date`: Converts and formats dates. | ||
|
||
### **6. Middleware** | ||
|
||
- **Custom Authentication Middleware**: | ||
- `withAuth`: Redirects unauthenticated users to the login page. | ||
|
||
### **7. Database Setup** | ||
|
||
- Utilized Sequelize to define and interact with PostgreSQL. | ||
- Seeded the database with initial user and project data. | ||
|
||
### **8. Client-Side Functionality** | ||
|
||
- **Login & Signup (public/js/login.js)**: | ||
- Handles user login and account creation. | ||
- Redirects users to the profile page upon successful authentication. | ||
- **Profile Management (public/js/profile.js)**: | ||
- Allows users to add new projects or delete existing ones. | ||
- **Logout (public/js/logout.js)**: | ||
- Ends the user's session and redirects them to the homepage. | ||
|
||
### **9. Server-Side Configuration** | ||
|
||
- Configured `express-session` with Sequelize as the session store. | ||
- Used `dotenv` to manage environment variables. | ||
- Set up Handlebars as the templating engine for server-rendered views. | ||
|
||
## How to Use | ||
|
||
1. Clone the repository and install dependencies using `npm install`. | ||
2. Create a `.env` file with the following variables: | ||
```env | ||
DB_NAME=your_database_name | ||
DB_USER=your_database_user | ||
DB_PASSWORD=your_database_password | ||
DB_URL=your_database_url # Optional for hosted databases | ||
``` | ||
3. Seed the database with `npm run seed`. | ||
4. Start the application with `npm start`. | ||
5. Access the app in your browser at `http://localhost:3001`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 0 additions & 2 deletions
2
12-model-view-controller/00-mini-project/controllers/api/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
12-model-view-controller/00-mini-project/controllers/homeRoutes.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
const router = require('express').Router(); | ||
const { Project, User } = require('../models'); | ||
const withAuth = require('../utils/auth'); | ||
|
||
router.get('/', async (req, res) => { | ||
try { | ||
// Get all projects and JOIN with user data | ||
const projectData = await Project.findAll({ | ||
include: [ | ||
{ | ||
model: User, | ||
attributes: ['name'], | ||
}, | ||
], | ||
}); | ||
|
||
// Serialize data so the template can read it | ||
const projects = projectData.map((project) => project.get({ plain: true })); | ||
|
||
// Pass serialized data and session flag into template | ||
res.render('homepage', { | ||
projects, | ||
logged_in: req.session.logged_in | ||
}); | ||
} catch (err) { | ||
res.status(500).json(err); | ||
} | ||
}); | ||
|
||
router.get('/project/:id', async (req, res) => { | ||
try { | ||
const projectData = await Project.findByPk(req.params.id, { | ||
include: [ | ||
{ | ||
model: User, | ||
attributes: ['name'], | ||
}, | ||
], | ||
}); | ||
|
||
const project = projectData.get({ plain: true }); | ||
|
||
res.render('project', { | ||
...project, | ||
logged_in: req.session.logged_in | ||
}); | ||
} catch (err) { | ||
res.status(500).json(err); | ||
} | ||
}); | ||
|
||
// Use withAuth middleware to prevent access to route | ||
router.get('/profile', withAuth, async (req, res) => { | ||
try { | ||
// Find the logged in user based on the session ID | ||
const userData = await User.findByPk(req.session.user_id, { | ||
attributes: { exclude: ['password'] }, | ||
include: [{ model: Project }], | ||
}); | ||
|
||
const user = userData.get({ plain: true }); | ||
|
||
res.render('profile', { | ||
...user, | ||
logged_in: true | ||
}); | ||
} catch (err) { | ||
res.status(500).json(err); | ||
} | ||
}); | ||
|
||
router.get('/login', (req, res) => { | ||
// If the user is already logged in, redirect the request to another route | ||
if (req.session.logged_in) { | ||
res.redirect('/profile'); | ||
return; | ||
} | ||
|
||
res.render('login'); | ||
}); | ||
|
||
module.exports = router; |
6 changes: 3 additions & 3 deletions
6
12-model-view-controller/00-mini-project/controllers/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
// Import just the router express | ||
const router = require('express').Router(); | ||
// Import the index.js from 'api' folder | ||
|
||
const apiRoutes = require('./api'); | ||
const homeRoutes = require('./homeRoutes'); | ||
|
||
// When a request is made to the /api route, it will be directed to the index.js in the 'api' folder. | ||
router.use('/', homeRoutes); | ||
router.use('/api', apiRoutes); | ||
|
||
module.exports = router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.