ShipNow LogoShipNow

Dashboard

Learn how to customize and extend your ShipNow dashboard with menus, new pages, and tables.

Overview

The ShipNow dashboard provides a flexible and customizable interface for managing your application. This guide walks you through creating a dashboard page and adding a table, including:

  • 📋 Adding and customizing navigation menus
  • 🎨 Creating new pages
  • 📊 Implementing data tables

Adding Navigation Menus

The dashboard menu is configured in components/dashboard-layout.tsx. Here's how to add new menu items:

Find the navItems array in the DashboardSidebar component:

components/dashboard-layout.tsx
const navItems = [
  { name: t("billing"), href: "/billing", icon: TbCreditCard },
];

Add new items to the navItems array.

components/dashboard-layout.tsx
import { TbDashboard, TbSettings, TbCreditCard } from "react-icons/tb";
 
const navItems = [
  { name: t("billing"), href: "/billing", icon: TbCreditCard },
  { name: t("newPages"), href: "/new-pages", icon: TbSettings },
];

Add corresponding translation keys in your locale files:

messages/en.json
{
  "dashboard": {
    "billing": "Billing",
    "newPages": "New Pages"
  }
}

Creating Dashboard Pages

Create a new page file in the app/[locale]/(dashboard) directory:

app/[locale]/(dashboard)/new-pages/page.tsx
import { useTranslations } from 'next-intl';
 
export default function NewPages() {
  const t = useTranslations('newPages');
 
  return (
    <div className="space-y-6">
      <h2 className="text-2xl font-bold mb-0">{t('title')}</h2>
      <p className="text-muted-foreground mb-4">{t('description')}</p>
    </div>
  )
}

Add corresponding translation keys in your locale files:

messages/en.json
{
  "newPages": {
    "title": "Page Title",
    "description": "Page description goes here."
  }
}

The page will be displayed in the dashboard layout like below:

Dashboard new pages example

Implementing Data Tables

ShipNow uses Shadcn's DataTable component with Tanstack Table for powerful data table features.

Create a table file with columns configuration.

The table component is a client component, so we put it in a new file.

app/[locale]/(dashboard)/new-pages/table.tsx
'use client';
 
import { useDataTable } from "@/hooks/use-data-table";
import { Badge } from "@/components/ui/badge";
import { useTranslations } from "next-intl";
import { DataTable } from "@/components/ui/data-table";
 
interface Order {
  id: string;
  product_name: string;
  mode: string;
  amount: number;
  paid_at: string;
}
 
interface TableProps {
  data: {
    data: Order[];
    total: number;
  };
}
 
const Table = ({ data }: TableProps) => {
  const t = useTranslations("billing");
 
  const { table } = useDataTable({
    data: data.data,
    total: data.total,
    columns: [
      {
        accessorKey: "product_name",
        header: t("product"),
      },
      {
        accessorKey: "mode",
        header: t("type"),
        cell: ({ row }) => {
          return (
            <Badge variant="outline">
              {row.getValue("mode")}
            </Badge>
          )
        },
      },
      {
        accessorKey: "amount",
        header: t("amount"),
        cell: ({ row }) => {
          return `$${(row.getValue("amount") as number).toFixed(2)}`;
        },
      },
      {
        accessorKey: "paid_at",
        header: t("paidAt"),
      },
    ],
  });
 
  return (
    <DataTable
      table={table}
    />
  );
};
 
export default Table;

Add the table component to your page:

app/[locale]/(dashboard)/new-pages/page.tsx
import { useTranslations } from "next-intl";
import Table from "./table";
 
export default function NewPagesPage() {
  const t = useTranslations('newPages');
 
  // Read data from the database
  const data = {
    total: 2,
    data: [
      {
        id: "1",
        product_name: "Product 1",
        mode: "One-time",
        amount: 100,
        paid_at: "2025-01-01"
      },
      {
        id: "2",
        product_name: "Product 2",
        mode: "Monthly",
        amount: 200,
        paid_at: "2025-01-02"
      }
    ]
  };
 
  return (
    <div className="space-y-6">
      <h2 className="text-2xl font-bold mb-0">{t('title')}</h2>
      <p className="text-muted-foreground mb-4">{t('description')}</p>
      <Table data={data}/>
    </div>
  )
}

The page with table will be displayed in the dashboard layout like below:

Dashboard new pages example

Need Help?

  • Join our Discord community
  • Open an issue on GitHub

On this page

ShipNow LogoGet ShipNow