Skip to content

Prashanthsyntax/E-Commerce

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

29 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

QuickCart - E-commerce Order Management System

QuickCart is a modern, full-stack e-commerce application designed to simplify order processing and management. It features seamless user authentication via Clerk, efficient cart and order handling, and background processing of orders with Inngest event workflows.

This project demonstrates:

  • User registration and authentication
  • Dynamic cart management with real-time calculations
  • Order creation with address selection and promo code support
  • Asynchronous order processing using Inngest for scalable background jobs
  • Seller dashboard to view and manage orders
  • Integration with MongoDB for data persistence

Built using Next.js, MongoDB, and integrated with Clerk and Inngest, QuickCart offers a robust foundation for scalable e-commerce platforms.


Prerequisites

  • Node.js (v16+ recommended)
  • npm or yarn
  • MongoDB database (local or cloud e.g., MongoDB Atlas)
  • Clerk account for authentication
  • Inngest account for event handling
  • Cloudinary account for Image handling

Steps to Setup

1. Clone the Repository

git clone https://github.com/yourusername/your-repo-name.git

cd your-repo-name

2. Dependencies

This project uses the following main dependencies:

  • Next.js (next) β€” React framework for server-rendered apps and static sites.
  • React (react, react-dom) β€” UI library.
  • Mongoose (mongoose) β€” MongoDB object modeling for Node.js.
  • Clerk (@clerk/nextjs) β€” Authentication and user management.
  • Axios (axios) β€” Promise based HTTP client for API requests.
  • Inngest (inngest) β€” Event-driven workflows and background jobs.
  • Cloudinary (cloudinary) β€” Image and media management.
  • React Hot Toast (react-hot-toast) β€” Notifications and toast messages.
  • Tailwind CSS (tailwindcss) β€” Utility-first CSS framework for styling.

Dev Dependencies

  • ESLint (eslint, eslint-config-next, @eslint/eslintrc) β€” Linting and code quality.
  • PostCSS (postcss) β€” CSS processor for Tailwind and other plugins.

Installing Dependencies

Run this command to install all dependencies:

npm install
# or
yarn install

3. Configure Environment Variables

Public Environment Variables

NEXT_PUBLIC_CURRENCY=$ NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_your_public_key_here

Private Environment Variables

CLERK_SECRET_KEY=sk_test_your_secret_key_here MONGODB_URI='mongodb+srv://username:password@cluster0.mongodb.net/your-db-name' INNGEST_SIGNING_KEY='your_inngest_signing_key_here' INNGEST_EVENT_KEY='your_inngest_event_key_here'

Cloudinary

CLOUDINARY_CLOUD_NAME='your_cloudinary_cloud_name' CLOUDINARY_API_KEY='your_cloudinary_api_key' CLOUDINARY_API_SECRET='your_cloudinary_api_secret'

4. Run the Development Server

npm run dev
# or
yarn dev

Work of Project and Brief idea on E-Commerce Website

Fetching User Data from API

REFER FILES: AppContext.jsx, api/user/data/route.js,

Actors / Components

  • User β†’ The person using the web app
  • Client Component (AppContextProvider) β†’ Runs in browser, calls API
  • Next.js API Route (/api/user/data) β†’ Server-side logic to get DB data
  • MongoDB via User model β†’ Database
  • Clerk Auth β†’ Validates and provides userId

Workflow

  • User loads the app and signs in with Clerk.

  • AppContextProvider detects user from useUser() and calls fetchUserData().

  • fetchUserData():

    • Checks if the user.publicMetadata.role is "seller" β†’ sets isSeller.
    • Gets an auth token via getToken() from Clerk.- Calls Axios GET /api/user/data with the token in the Authorization header.
  • API Route /api/user/data:

    • Uses getAuth(request) from Clerk to extract userId from the request.
    • Connects to MongoDB via connectDB().
    • Finds the user document with User.findById(userId).
    • Returns { success: true, user } or an error.
  • AppContextProvider receives the API response:

    • Updates userData state.
    • Updates cartItems state.
  • UI updates automatically with new userData and cartItems.


Sellers API's and Products

Products

Method Route Description
POST /api/product/add Add a new product (sellers only)
GET /api/product/list Fetch all products
GET /api/product/seller Fetch seller’s products (sellers only)
GET /api/order/seller-orders Fetch all orders for authorized sellers

REFER FOLDER : Product,

βš™οΈ Tech Stack

  • Next.js (App Router API routes)
  • MongoDB with Mongoose ORM
  • Cloudinary for media storage
  • Clerk for authentication and role management
  • JavaScript / ES Modules

πŸš€ Workflow Overview

1. Add a Product

File: /app/api/product/add/route.js
Method: POST
Flow:

  1. Authentication

    • Uses getAuth() from @clerk/nextjs/server to get userId.
    • Calls authSeller(userId) to ensure only sellers can add products.
  2. Get Form Data

    • Reads product fields: name, description, category, price, offerPrice.
    • Reads uploaded images from formData.
  3. Upload Images to Cloudinary

    • Converts uploaded file streams into buffers.
    • Uploads them to Cloudinary using upload_stream.
  4. Save Product to MongoDB

    • Connects to MongoDB (connectDB()).
    • Creates a new Product document with images and details.
  5. Response

    • Returns JSON { success: true, product: "Upload successful", newProduct }.

2. Get All Products

File: /app/api/product/list/route.js
Method: GET
Flow:

  1. Connect to MongoDB.
  2. Fetch all products using Product.find({}).
  3. Return them in JSON: { success: true, products }.

3. Get Seller's Products

File: /app/api/product/seller/route.js
Method: GET
Flow:

  1. Authentication & Authorization

    • Get userId from Clerk.
    • Verify seller role with authSeller(userId).
  2. Fetch Products

    • Connect to MongoDB.
    • Fetch all products (optionally could filter by userId for seller-specific data).
  3. Response

    • Return { success: true, products } or { success: false, message }.

Seller Orders Feature

Workflow

  1. Authentication & Authorization

    • The API uses Clerk to authenticate the user via getAuth(request) which returns userId.
    • The user is verified as a seller by calling a custom authSeller(userId) function.
    • If the user is not a seller, the API returns an error with success: false and message "not authorized".
  2. Database Connection

    • Connect to MongoDB with connectDB().
  3. Fetch Orders

    • Fetch all orders from the Order collection.
    • Use .populate('address items.product') to fetch detailed information for the order’s address and product(s).
  4. Return Response

    • Return the list of populated orders with success: true.
    • If an error occurs, return success: false and the error message.

Frontend: Seller Orders Page (React Component)

refer: app\seller\orders\page.jsx

Component: Orders

  • Fetches seller orders from the backend API endpoint /api/order/seller-orders.
  • Uses the getToken method from your app context to include an Authorization header with the JWT token.
  • Displays a loading spinner while fetching.
  • Displays a list of orders with the following details:
    • Product names and quantities.
    • Address information (full name, area, city, state, phone number).
    • Order amount displayed with currency.
    • Payment method (hardcoded as COD here), date, and payment status.
  • Uses react-hot-toast to show error messages if fetching fails.
  • Uses a Footer component for page footer.

Important Notes

  • Requires the user to be logged in (tracked via user from app context).
  • Orders are shown in the order received from the backend.
  • Uses Next.js Image component to render a box icon for each order.

CART API's

To GET and Update

Cart

Method Route Description
GET /api/cart/get Get the current user's cart
POST /api/cart/update Update the user's cart

πŸš€ Workflow

1. Cart Management

πŸ“₯ Get Cart (GET /api/cart/get)

Flow:

  1. Authentication

    • getAuth(request) retrieves the current userId from Clerk.
  2. Database Connection

    • connectDB() connects to MongoDB.
  3. Fetch User Data

    • Find the user by userId in the User collection.
    • Extract cartItems from the user document.
  4. Response

    • Returns { success: true, cartItems }.

✏️ Update Cart (POST /api/cart/update)

Flow:

  1. Authentication

    • Get userId from Clerk.
  2. Request Parsing

    • Read cartData from the request body (JSON).
  3. Database Update

    • Find the user by userId.
    • Replace user.cartItems with cartData.
    • Save the updated user document.
  4. Response

    • Returns { success: true, message: "Cart updated successfully" }.

πŸ“ Address API's

REFER FOLDER: app/user files...

To GET and Add User Addresses

Address

Method Route Description
GET /api/user/get-address Get the current user's saved addresses
POST /api/user/add-address Add a new address for the current user

πŸš€ Workflow

1. Address Management


πŸ“₯ Get Addresses (GET /api/user/get-address)

Flow:

  1. Authentication

    • getAuth(request) retrieves the current userId from Clerk.
  2. Database Connection

    • connectDB() establishes a connection to MongoDB.
  3. Fetch Addresses

    • Query the Address collection with { userId }.
    • Retrieve all address documents belonging to that user.
  4. Response

    • Returns:
      { "success": true, "addresses": [...] }

βž• Add Address (POST /api/user/add-address)

Flow:

  1. Authentication

    • Get userId from Clerk.
  2. Request Parsing

    • Read the address object from the request body (JSON).
  3. Database Insert

    • Create a new document in the Address collection using:
      { ...address, userId }
  4. Response

    • Returns:
      { "success": true, "message": "Address added successfully", "newAddress": { ... } }

πŸ“¦ Order API's

To Create and Process User Orders

Order

Method Route Description
POST /api/order/create Create a new order for the current user (processed asynchronously via Inngest)
GET /api/order/list Get all orders for the current authenticated user

πŸš€ Workflow

1. Order Creation


πŸ›’ Create Order (POST /api/order/create)

Flow:

  1. Authentication

    • The API uses getAuth(request) (Clerk) to retrieve the current user's userId.
  2. Request Parsing

    • The request body must include:
      • address: the selected address's ID
      • items: an array of items with { product, quantity }
    • If address is missing or items is empty, it returns:
      { "success": false, "message": "Invalid data" }
  3. Amount Calculation

    • For each item in items, the product document is fetched using Product.findById(item.product).
    • The total amount is calculated as the sum of (product.offerPrice * quantity) for all items.
    • An additional 2% tax/fee is added to the total amount.
  4. Send Order Event (Async Processing)

    • Using inngest.send(), an event named "order/created" is emitted with this payload:
      {
        "userId": "user-id-here",
        "address": "address-id-here",
        "items": [...],
        "amount": 1234,
        "date": 1689200000000
      }
  5. Clear User Cart

    • Finds the user by userId in the database (User.findById(userId)).
    • Clears the cartItems by setting it to {} and saves the user document.
  6. Response

    • Returns JSON:
      { "success": true, "message": "Order created successfully" }

2. Order Processing (Inngest Function)


βš™οΈ create-user-order Function

Triggered by: order/created event.

Flow:

  1. Batch Processing

    • This Inngest function collects up to 5 events or waits 5 seconds before processing.
  2. Order Mapping

    • Maps each event's data to a new order object with keys:
      {
        "userId": "...",
        "items": [...],
        "amount": "...",
        "address": "...",
        "date": "..."
      }
  3. Database Connection and Insertion

    • Connects to MongoDB (connectDB()).
    • Inserts the mapped orders into the Order collection using Order.insertMany().
  4. Response

    • Returns:
      { "success": true, "processed": <number_of_orders_inserted> }

3. Get Orders for User


πŸ“„ List Orders (GET /api/order/list)

Flow:

  1. Authentication

    • Uses getAuth(request) to get the userId.
  2. Fetch Orders

    • Queries the Order collection filtering by userId.
    • Uses .populate('address items.product') to fetch related Address and Product details for each order.
  3. Response

    • Returns JSON with all the populated orders for the user:
      { "success": true, "orders": [...] }

⚠️ Important Notes

  • Schema Types:

    • Order.address must be an ObjectId referencing the "Address" model for populate to work correctly.
    • Order.items.product must be an ObjectId referencing the "Product" model.
  • Populate works only if ref and types are set correctly in your Mongoose schemas.



πŸŽ‰ You're All Set!

Thank you for checking out this project. If you run into any issues or have questions, feel free to open an issue or reach out. Happy coding and enjoy building with this e-commerce platform!


About

E-commerce Website for Buyers and Sellers

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages