Skip to content

Repository files navigation

SEAPEDIA

SEAPEDIA is a full-stack marketplace built for the COMPFEST 18 Software Engineering Academy challenge. It supports guest browsing, multi-role authentication, seller store management, buyer checkout, driver delivery, and admin monitoring in one monorepo.

Backend authorization is driven by the user's selected active role, so one account can hold several roles but only acts with the one it has activated.

Features

  • Public marketplace: guests can browse products, stores, product details, and public application reviews.
  • Authentication: registration, login, JWT authentication, and active-role selection.
  • Multi-role users: one account can own multiple roles, but protected workflows authorize against the selected activeRole.
  • Seller workflow: create stores, manage products, process incoming orders, and view income reports.
  • Buyer workflow: wallet top-up, transaction history, addresses, single-store cart, checkout, order history, and spending reports.
  • Checkout rules: subtotal, one voucher or promo code, PPN 12%, delivery fee, stock updates, and wallet payment.
  • Driver workflow: discover available delivery jobs, claim jobs, complete deliveries, and view earnings.
  • Admin workflow: monitoring, voucher/promo management, user creation, simulated time advance, and overdue order processing.
  • Order lifecycle: SEDANG_DIKEMAS, MENUNGGU_PENGIRIM, SEDANG_DIKIRIM, PESANAN_SELESAI, and DIKEMBALIKAN.

Tech Stack

  • Monorepo: npm workspaces
  • Frontend: React, Vite, TypeScript, Tailwind CSS, lucide-react
  • Backend: NestJS, TypeScript, JWT, class-validator
  • Database: PostgreSQL 15 through Docker Compose
  • ORM: Prisma
  • Testing: Jest and Supertest for the API

Project Structure

.
|-- apps
|   |-- api                 # NestJS API, Prisma schema, migrations, seed data
|   `-- web                 # React/Vite single-page application
|-- docs                    # Requirements, API reference, and testing guide
|-- docker-compose.yaml     # Local PostgreSQL service
|-- package.json            # Root workspace scripts
`-- README.md

Prerequisites

  • Node.js and npm
  • Docker Desktop or another Docker Compose-compatible runtime
  • Git

Quick Start with Docker

This is the fastest way to run the whole stack. It starts PostgreSQL, the API, and the web app, applies migrations, and seeds demo data automatically.

  1. Create the environment file.

    Copy-Item .env.example .env
  2. Build and start everything.

    docker compose up --build
  3. Open the web app at http://localhost:5173. The API is at http://localhost:3000 and Swagger UI at http://localhost:3000/docs.

The database is seeded on startup with the demo accounts, catalog, discounts, and a sample in-delivery order, so every dashboard has data on first load. Log in with any account from Demo Accounts.

Local Setup (without Docker)

  1. Install dependencies.

    npm install
  2. Create the root environment file.

    Copy-Item .env.example .env
  3. Start PostgreSQL.

    npm run db:up
  4. Run Prisma migration, generate the client, and seed demo data.

    npm run prisma:migrate
    npm run prisma:generate
    npm run db:seed
  5. Start the API and web app in separate terminals.

    npm run dev:api
    npm run dev:web

By default, the API runs on http://localhost:3000. The Vite dev server prints the web URL in the terminal, usually http://localhost:5173.

Environment Variables

The root .env is used by Docker Compose and the API's local database connection.

POSTGRES_USER=seapedia_admin
POSTGRES_PASSWORD=seapedia_secret
POSTGRES_DB=seapedia_db
DATABASE_URL="postgresql://seapedia_admin:seapedia_secret@localhost:5432/seapedia_db?schema=public"
PORT=3000
JWT_SECRET=change-me-in-local-development
WEB_ORIGIN=http://localhost:5173

WEB_ORIGIN is the comma-separated list of browser origins allowed to call the API (CORS). If it is not set, the API allows http://localhost:5173, the default Vite dev server origin.

The web app reads VITE_API_URL. If it is not set, it defaults to http://localhost:3000.

Demo Accounts

All seeded demo accounts use password password123.

Role Email
Admin admin@seapedia.test
Seller seller@seapedia.test
Buyer buyer@seapedia.test
Driver driver@seapedia.test
Multi-role multi@seapedia.test

After login, choose an active role before using private dashboards or role-protected API endpoints.

Useful Scripts

Command Purpose
npm run db:up Start the PostgreSQL container
npm run db:down Stop Docker Compose services
npm run db:logs Stream PostgreSQL logs
npm run dev:api Start the NestJS API in watch mode
npm run dev:web Start the Vite web app
npm run build:api Build the API
npm run build:web Build the web app
npm run test:api Run API unit tests
npm run lint:api Lint and fix API files
npm run lint:web Lint the web app
npm run prisma:migrate Apply Prisma migrations in development
npm run prisma:generate Generate Prisma Client
npm run db:seed Seed demo users, products, discounts, and related data
npm run setup:check Validate Docker Compose configuration

Core API Areas

  • POST /auth/register, POST /auth/login, POST /auth/select-role, POST /auth/roles, GET /auth/me
  • GET /products, GET /stores, GET /reviews, POST /reviews
  • Seller endpoints for stores, products, order processing, and income reports
  • Buyer endpoints for wallet, addresses, cart, checkout, orders, and spending reports
  • Driver endpoints for available jobs, claimed jobs, completion, and earnings
  • Admin endpoints for monitoring, vouchers, promos, users, simulated time, and overdue processing

Interactive Swagger UI is served at GET /docs (OpenAPI JSON at /docs-json) while the API is running. See docs/seapedia-api-reference.md for the offline endpoint reference.

Business Rules

  • Protected role APIs authorize against the JWT's selected activeRole.
  • A registered account starts as a Buyer and can self-add the SELLER and/or DRIVER role from the account panel (POST /auth/roles), then select it to activate. ADMIN is not self-grantable and is created only through seed data or the protected admin user endpoint.
  • Guests can browse catalog data and create public application reviews.
  • A cart can contain products from one store only.
  • Checkout calculates subtotal - discount + PPN 12% + delivery fee.
  • One checkout discount code is accepted and resolved as either a voucher or promo.
  • Seller order processing creates the delivery job.
  • A driver can claim an available delivery job only once.
  • Overdue processing is idempotent: it refunds the buyer wallet, restores stock, marks delivery returned, writes status history, and records the processing log.

Security

  • SQL injection: all database access goes through Prisma's parameterized query API; there are no raw string-concatenated SQL queries.
  • XSS: user-generated content (application reviews and comments) is rendered as text through React, which escapes it by default. The app does not use dangerouslySetInnerHTML.
  • Input validation: a global ValidationPipe (whitelist, forbidNonWhitelisted, transform) plus class-validator DTOs validate and reject unexpected or malformed fields (email, phone, rating, quantity, price, stock, discount values) with clear error messages.
  • Session behavior: authentication uses JWT bearer tokens signed with JWT_SECRET and expiring after 1d. Logout clears the token on the client, and protected requests are rejected once the token expires.
  • Role-based access control: protected endpoints are guarded server-side by JwtAuthGuard and an ActiveRoleGuard that authorizes against the token's selected activeRole, not the full role list. Ownership checks prevent acting on another user's store, order, or job. Admin-only endpoints are not reachable by non-admin roles.
  • Security headers: helmet sets standard hardening headers (X-Content-Type-Options, X-Frame-Options, HSTS, etc.). Its Content-Security-Policy is disabled so the self-hosted Swagger UI at /docs renders correctly.
  • Rate limiting: @nestjs/throttler applies a global limit of 100 requests/minute per IP, tightened to 5 requests/minute on the public write endpoints POST /auth/login, POST /auth/register, and POST /reviews to blunt brute-force and spam. Exceeding a limit returns 429 Too Many Requests.

Testing and Demo Flow

Run the API tests with:

npm run test:api

For manual acceptance testing:

  1. Browse products, stores, and reviews as a guest.
  2. Submit a public review.
  3. Login as seller, select SELLER, create a store/product, then confirm it appears in the public catalog.
  4. Login as buyer, select BUYER, top up wallet, add an address, add a product to cart, and checkout with HEMAT10K or PROMO10.
  5. Login as seller again and process the new order.
  6. Login as driver, select DRIVER, claim the available job, then complete it.
  7. Login as admin, select ADMIN, inspect monitoring, create discounts, advance simulated time, and process overdue orders.

See docs/seapedia-testing-guide.md for the full testing guide.

Documentation

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages