Skip to content

Sales Management Dashboard ‐ Documentation

Phosky edited this page Jan 27, 2025 · 3 revisions

1. Project Overview

The application is a sales management dashboard built with Next.js 15 using the App Router.

The app relies on a PostgreSQL database, hosted on Vercel, using Kysely as the ORM for database management and queries. NextAuth.js handles user authentication, shadcn/ui provides the component library, and Tailwind CSS is used for styling. The project is deployed on Vercel.

The following routes are included:

  • /sign-in: User sign-in page.
  • /sign-up: User sign-up page.
  • /dashboard: Displays total sales summaries, top sellers, and a chart showing monthly sales from the previous year.
  • /dashboard/invoices: Shows a table with all invoices, optimized for over 1,000 entries.
  • /dashboard/sellers: Lists all sellers in a table view.
  • /seed: Resets the database by recreating table structures and seeding new test data.

Project Structure

The main folders in the project structure are:

  • Root Folder:

    • __tests__: Unit tests.
    • cypress: E2E tests.
    • public: Public assets.
    • src: Application logic and source code.
  • Inside src Folder:

    • src/app: Defines the routing structure, and layouts.
    • src/components: All application components.
    • src/components/ui: For UI components.
    • src/hooks: Custom hooks.
    • src/lib: Server actions, database access functions, and utilities.
    • src/schemas: Zod schemas for validation.
    • src/types: Type definitions.

2. Design Decisions

This project primarily uses SSR for all components, limiting client components to essential cases. Server actions are used for server data access from client components, a recommended practice in recent Next.js versions with App Router, as it enables direct access to server data without setting up specific API routes (though it functions similarly under the hood).

For authentication, the project uses NextAuth.js v5 configured with the Credentials provider. The configuration is set up across two separate files for clarity and modularity, following NextAuth's recommendations:

  • /src/auth.config.ts defines the basic configuration, including a middleware to protect routes.
  • /src/auth.ts imports this configuration and defines the Credentials provider setup, as well as utility functions for sign-in and sign-out logic. This file includes the sign-in logic.
  • signInAction and signUpAction server actions are defined in /src/lib/auth-actions.ts and are used in components for authentication handling.

I chose shadcn/ui as a UI components library over building components from scratch because it closely aligns with a professional setup—using components that are both highly accessible and well-tested. Shadcn/ui provides components through a CLI that adds the source code right into the project. This setup gives me complete control to customize the components however I need, both in terms of functionality and design.

Using shadcn/ui has also sped up the development of this project, letting me focus on other key details and be more productive overall.

Lastly, it’s worth noting that in Tailwind CSS 3, Just-In-Time (JIT) mode is enabled by default.

3. Domain Model

The database schema includes the following tables:

  • User Table: Stores user id, name, email, and password.
  • Seller Table: Stores seller id, name, email, and avatar.
  • Invoice Table: Stores invoice id, status, amount, paymentMethod, sellerId, and createdAt.

4. Theme System

A theme-toggle component (theme-toggle.tsx) is accessible from all pages, allowing users to switch between light, dark, or system themes. This functionality is managed by a theme-provider.tsx component using the next-themes library, which handles the theme state.

5. Custom Hook: useScrollPagination

The custom hook useScrollPagination (located in src/hooks/useScrollPagination.tsx) manages fetching additional data as the user scrolls through a list, such as in a table. This hook leverages the Intersection Observer API to detect scrolling activity and automatically load more data as needed. It’s used in the invoices-table.tsx and sellers-table.tsx components, which can be seen in action on the /dashboard/invoices and /dashboard/sellers routes.

useScrollPagination Hook Code Explanation

The useScrollPagination hook is designed for efficient data fetching when scrolling:

  • Parameters:

    • fetchDataAction: The async function for fetching data.
    • initialData: Initial dataset.
    • limit: Number of records to fetch at a time.
    • refToObserve: Reference to the DOM element triggering additional data loading.
  • State Management:

    • data: Holds all fetched data.
    • offset: Tracks the current offset.
    • hasMoreData: Tracks if there’s more data to fetch.
  • Intersection Observer:

    • Observes refToObserve. When it intersects, handleIntersection is triggered to load more data.

6. Performance Optimization

To optimize the application, the following strategies are applied:

  • SSR: Used on almost all components, except where client components are strictly necessary.
  • Prefetching: Link components from Next.js are used, which support prefetching to reduce loading times. More info: Next.js Link Documentation.
  • Lighthouse Testing: The application scores 99 for performance, accessibility, best practices, and SEO in Google Lighthouse, specifically on mobile.

Production Testing was completed using the deployed version at: a-safe-technical-test-roan.vercel.app

7. Testing

Due to Cypress not yet supporting component tests in Next.js 14 or higher (see warning), I have opted to use Jest for component tests and Cypress for end-to-end (E2E) tests.

  • Jest is used for component testing, with tests stored in the __tests__ folder at the project root.
  • Cypress is used for E2E testing, located in the cypress folder.
  1. To run the tests, use the following commands:

    Unit tests:

    pnpm run test

    E2E tests:

    pnpm run build && pnpm run start
    
    // In a new terminal, open Cypress:
    pnpm run cypress:open

8. Instructions for Running the Project

  1. Ensure Node.js (version 18.18 or above) and pnpm are installed on your system.

    • If not installed, download Node.js from nodejs.org and install pnpm globally using:
      npm install -g pnpm
  2. Clone the repository:

    git clone https://github.com/MarioMS90/sales-management-dashboard
  3. Install project dependencies:

    pnpm install
  4. Create a project and a PostgreSQL database on Vercel:

    Add the necessary keys to a .env.local file in the root of the project to set up the environment variables.

  5. Initialize the database structure and seed data:

    Visit http://localhost:3000/seed to create the database tables and populate them with sample data.

  6. Start the local development server:

    pnpm run dev

    Default user for login:

  7. To run the tests, use the following commands:

    Unit tests:

    pnpm run test

    E2E tests:

    pnpm run build && pnpm run start
    
    // In a new terminal, open Cypress:
    pnpm run cypress:open