Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d70b083
Initial Commit
bhdoggett Apr 1, 2025
0dbe5e6
Add fake data for products with working references to reviews
bhdoggett Apr 2, 2025
f8bf259
GET product reviews complete
bhdoggett Apr 3, 2025
dc2c922
POST /products complete
bhdoggett Apr 3, 2025
a673bcb
Add middlware to validate and get product from routes with productId …
bhdoggett Apr 3, 2025
1891786
Add error handling for page parameters that exceed the resulting data
bhdoggett Apr 4, 2025
9eb5d8d
Complete DELETE review route
bhdoggett Apr 4, 2025
67b4e91
GET '/products' - add optional filter by search or category and add o…
bhdoggett Apr 4, 2025
649586d
Add next-js frontend. Reconfigure diretory structure for monorepo.
bhdoggett Apr 4, 2025
75fb1e3
Add component files to frontend
bhdoggett Apr 4, 2025
5a1bbdb
Add Redux Provider to layout.tsx
bhdoggett Apr 5, 2025
9de9348
Can get products to frontend
bhdoggett Apr 7, 2025
aa90479
WIP updating state and rerouting from query params.
bhdoggett Apr 7, 2025
45d44c7
WIP Product component, styling and image
bhdoggett Apr 7, 2025
7755503
Update filter components. Update fetchProducts to return page of prod…
bhdoggett Apr 8, 2025
ddc6e41
Update GET /products to return page of products AND total page count.
bhdoggett Apr 8, 2025
6f6cc7b
Add fetchCategories to product slice. Add number query parameter to G…
bhdoggett Apr 8, 2025
a50df3b
Add dynamic category text to product page
bhdoggett Apr 8, 2025
da2836e
Remove unneccesary router.push from categories, priceSort and searchB…
bhdoggett Apr 8, 2025
116f2e1
Remove other unnecessary code
bhdoggett Apr 8, 2025
8e36977
Update placeholder product image and general styling.
bhdoggett Apr 10, 2025
eee462a
Update README.md and move to root directory.
bhdoggett Apr 10, 2025
e46a050
Hot pink.
bhdoggett Apr 10, 2025
92e52f6
Refactor GET /products for better mongo backward compatibility
bhdoggett Apr 15, 2025
4869f7e
Add 'await' to product.save and review.save.
bhdoggett Apr 15, 2025
402fca1
Remove console logs
bhdoggett Apr 24, 2025
83c7e14
Add fallback url for BASE_PATH if .env variable not present
bhdoggett Apr 24, 2025
7537d8e
Add database connection check in server.js
bhdoggett Jun 2, 2025
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
67 changes: 67 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# ----------------------
# GENERAL IGNORE RULES
# ----------------------

# Dependencies
node_modules/
frontend/node_modules/
backend/node_modules/
.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# Testing
coverage/

# Logs
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# ----------------------
# NEXT.JS FRONTEND
# ----------------------

# Next.js build output
frontend/.next/
frontend/out/

# Production build
frontend/build/

# Next.js env files (opt-in if needed)
frontend/.env*

# Next.js specific files
frontend/.vercel
frontend/next-env.d.ts
frontend/*.tsbuildinfo

# ----------------------
# EXPRESS BACKEND
# ----------------------

# Build output
backend/dist/
backend/build/

# Backend env files
backend/.env

# Debugging
backend/debug.log
backend/.eslintcache

# ----------------------
# MISC
# ----------------------

.DS_Store
*.pem
53 changes: 51 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,55 @@
## Product List

This project was created by a student at Parsity, an online software engineering course. The work in this repository is wholly the student's, based on a sample starter project that can be accessed by viewing the repository this project was forked from.

This project has been created by a student at Parsity, an online software engineering course. The work in this repository is wholly of the student based on a sample starter project that can be accessed by looking at the repository that this project forks.
If you have any questions about this project or the program, visit [parsity.io](https://parsity.io/) or email hello@parsity.io.

If you have any questions about this project or the program in general, visit [parsity.io](https://parsity.io/) or email hello@parsity.io.
---

**Product List** is a basic mock e-commerce webpage for displaying and filtering available products for purchase. The backend server supports `GET`, `POST`, and `DELETE` requests for products and reviews. (Note: the frontend currently only makes use of the `GET /products` route.)

This project uses **MongoDB** for data storage, with **Mongoose** to interact with the database on the backend. The frontend is built using **React** and **Next.js**.

---

### Getting Started

1. **Install MongoDB** to host a local database.
[MongoDB Installation Guide](https://www.mongodb.com/docs/manual/installation/)

2. **Start the backend server** from the root directory:

```bash
node backend/server.js
```

3. Populate your database by sending a GET request to:

```bash
http://localhost:8000/generate-fake-data?number=<your-number>
```

If no number is provided, the server will default to generating 100 products.

4. Start the frontend development server. From the /frontend directory, run:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

5. Navigate to '<your-frontend-development-server>/products — this will automatically route to '/products?page=1'.

Products are displayed 9 at a time, with pagination at the bottom of the page. You can search by name, filter by category, and sort by highest or lowest price.

Tech Stack

- MongoDB + Mongoose
- Node.js + Express
- React + Next.js
- Tailwind CSS
18 changes: 18 additions & 0 deletions backend/middleware/validatePageFormat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const validatePageFormat = (req, res, next) => {
// If no page parameter is provided, ignore the page property
if (!req.query.page) {
req.page = null;
return next();
}

const page = parseInt(req.query.page);

if (isNaN(page) || page < 1) {
return res.status(400).json({ message: "Valid 'page' parameter required" });
}

req.page = page;
next();
};

export default validatePageFormat;
19 changes: 19 additions & 0 deletions backend/middleware/validateProduct.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Product } from "../models/product.js";
import mongoose from "mongoose";

// Middlware for routes that need to get a specific product
const validateProduct = async (req, res, next) => {
const { productId } = req.params;
if (!mongoose.Types.ObjectId.isValid(productId)) {
return res.status(400).json({ message: "Invalid product ID format" });
}

const product = await Product.findById(req.params.productId);

if (!product) return res.status(404).json({ message: "Product not found" });

req.product = product;
next();
};

export default validateProduct;
19 changes: 19 additions & 0 deletions backend/models/product.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import mongoose from "mongoose";

const productSchema = new mongoose.Schema({
category: { type: String, required: true },
name: { type: String, required: true },
price: { type: Number, required: true },
image: String,
reviews: [{ type: mongoose.Schema.Types.ObjectId, ref: "Review" }],
});

const reviewSchema = new mongoose.Schema({
userName: String,
product: { type: mongoose.Schema.Types.ObjectId, ref: "Product" },
text: String,
});

export const Product = mongoose.model("Product", productSchema);

export const Review = mongoose.model("Review", reviewSchema);
Loading