├── .eslintrc.json
├── public
├── dark.png
├── light.png
├── favicon.ico
└── vercel.svg
├── postcss.config.js
├── next.config.js
├── app
├── (auth)
│ ├── login
│ │ └── page.tsx
│ ├── register
│ │ └── page.tsx
│ └── layout.tsx
├── (app)
│ ├── accounts
│ │ └── page.tsx
│ ├── page.tsx
│ └── layout.tsx
├── layout.tsx
└── providers.tsx
├── components
├── hooks
│ ├── useIsomorphicLayoutEffect.ts
│ └── useBodyLock.ts
├── sidebar
│ ├── sidebar-menu.tsx
│ ├── sidebar-item.tsx
│ ├── sidebar.styles.ts
│ ├── companies-dropdown.tsx
│ ├── collapse-items.tsx
│ └── sidebar.tsx
├── layout
│ ├── layout-context.ts
│ └── layout.tsx
├── navbar
│ ├── darkmodeswitch.tsx
│ ├── burguer-button.tsx
│ ├── navbar.styles.ts
│ ├── notifications-dropdown.tsx
│ ├── user-dropdown.tsx
│ └── navbar.tsx
├── icons
│ ├── sidebar
│ │ ├── chevron-up-icon.tsx
│ │ ├── chevron-down-icon.tsx
│ │ ├── filter-icon.tsx
│ │ ├── products-icon.tsx
│ │ ├── bottom-icon.tsx
│ │ ├── accounts-icon.tsx
│ │ ├── payments-icon.tsx
│ │ ├── home-icon.tsx
│ │ ├── view-icon.tsx
│ │ ├── balance-icon.tsx
│ │ ├── reports-icon.tsx
│ │ ├── dev-icon.tsx
│ │ ├── customers-icon.tsx
│ │ ├── changelog-icon.tsx
│ │ └── settings-icon.tsx
│ ├── accounts
│ │ ├── info-icon.tsx
│ │ ├── dots-icon.tsx
│ │ ├── trash-icon.tsx
│ │ └── export-icon.tsx
│ ├── acmelogo.tsx
│ ├── searchicon.tsx
│ ├── breadcrumb
│ │ ├── users-icon.tsx
│ │ └── house-icon.tsx
│ ├── navbar
│ │ ├── github-icon.tsx
│ │ ├── support-icon.tsx
│ │ ├── notificationicon.tsx
│ │ └── feedback-icon.tsx
│ ├── table
│ │ ├── eye-icon.tsx
│ │ ├── edit-icon.tsx
│ │ └── delete-icon.tsx
│ ├── community.tsx
│ └── acme-icon.tsx
├── table
│ ├── table.tsx
│ ├── render-cell.tsx
│ └── data.ts
├── auth
│ ├── authLayout.tsx
│ ├── login.tsx
│ └── register.tsx
├── home
│ ├── card-agents.tsx
│ ├── card-balance3.tsx
│ ├── card-balance1.tsx
│ ├── card-balance2.tsx
│ ├── card-transactions.tsx
│ └── content.tsx
├── accounts
│ ├── add-user.tsx
│ └── index.tsx
└── charts
│ └── steam.tsx
├── styles
└── globals.css
├── helpers
├── types.ts
└── schemas.ts
├── actions
└── auth.action.ts
├── config
└── fonts.ts
├── tailwind.config.js
├── .gitignore
├── .github
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── middleware.ts
├── tsconfig.json
├── package.json
├── LICENSE
└── README.md
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/public/dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siumauricio/nextui-dashboard-template/HEAD/public/dark.png
--------------------------------------------------------------------------------
/public/light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siumauricio/nextui-dashboard-template/HEAD/public/light.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siumauricio/nextui-dashboard-template/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | };
5 |
6 | module.exports = nextConfig;
7 |
--------------------------------------------------------------------------------
/app/(auth)/login/page.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Login } from "@/components/auth/login";
3 |
4 | const login = () => {
5 | return ;
6 | };
7 |
8 | export default login;
9 |
--------------------------------------------------------------------------------
/app/(app)/accounts/page.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Accounts } from "@/components/accounts";
3 |
4 | const accounts = () => {
5 | return ;
6 | };
7 |
8 | export default accounts;
9 |
--------------------------------------------------------------------------------
/components/hooks/useIsomorphicLayoutEffect.ts:
--------------------------------------------------------------------------------
1 | import {useEffect, useLayoutEffect} from 'react';
2 |
3 | export const useIsomorphicLayoutEffect =
4 | typeof window !== 'undefined' ? useLayoutEffect : useEffect;
5 |
--------------------------------------------------------------------------------
/app/(app)/page.tsx:
--------------------------------------------------------------------------------
1 | import type { NextPage } from "next";
2 | import { Content } from "@/components/home/content";
3 |
4 | const Home: NextPage = () => {
5 | return ;
6 | };
7 |
8 | export default Home;
9 |
--------------------------------------------------------------------------------
/app/(auth)/register/page.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Register } from "@/components/auth/register";
3 |
4 | const register = () => {
5 | return ;
6 | };
7 |
8 | export default register;
9 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | html,
6 | body {
7 | padding: 0;
8 | margin: 0;
9 | }
10 |
11 | * {
12 | box-sizing: border-box;
13 | }
14 |
--------------------------------------------------------------------------------
/helpers/types.ts:
--------------------------------------------------------------------------------
1 | // FORMS
2 |
3 | export type LoginFormType = {
4 | email: string;
5 | password: string;
6 | };
7 |
8 | export type RegisterFormType = {
9 | name: string;
10 | email: string;
11 | password: string;
12 | confirmPassword: string;
13 | };
14 |
--------------------------------------------------------------------------------
/app/(app)/layout.tsx:
--------------------------------------------------------------------------------
1 | import { Layout } from "@/components/layout/layout";
2 | import "@/styles/globals.css";
3 |
4 | export default function RootLayout({
5 | children,
6 | }: {
7 | children: React.ReactNode;
8 | }) {
9 | return {children} ;
10 | }
11 |
--------------------------------------------------------------------------------
/actions/auth.action.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { cookies } from "next/headers";
4 |
5 | export const createAuthCookie = async () => {
6 | cookies().set("userAuth", "myToken", { secure: true });
7 | };
8 |
9 | export const deleteAuthCookie = async () => {
10 | cookies().delete("userAuth");
11 | };
12 |
--------------------------------------------------------------------------------
/app/(auth)/layout.tsx:
--------------------------------------------------------------------------------
1 | import { AuthLayoutWrapper } from "@/components/auth/authLayout";
2 | import "@/styles/globals.css";
3 |
4 | export default function RootLayout({
5 | children,
6 | }: {
7 | children: React.ReactNode;
8 | }) {
9 | return {children} ;
10 | }
11 |
--------------------------------------------------------------------------------
/config/fonts.ts:
--------------------------------------------------------------------------------
1 | import { Fira_Code as FontMono, Inter as FontSans } from "next/font/google"
2 |
3 | export const fontSans = FontSans({
4 | subsets: ["latin"],
5 | variable: "--font-sans",
6 | })
7 |
8 | export const fontMono = FontMono({
9 | subsets: ["latin"],
10 | variable: "--font-mono",
11 | })
12 |
--------------------------------------------------------------------------------
/components/sidebar/sidebar-menu.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | interface Props {
4 | title: string;
5 | children?: React.ReactNode;
6 | }
7 |
8 | export const SidebarMenu = ({ title, children }: Props) => {
9 | return (
10 |
11 | {title}
12 | {children}
13 |
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/components/layout/layout-context.ts:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { createContext, useContext } from "react";
4 |
5 | interface SidebarContext {
6 | collapsed: boolean;
7 | setCollapsed: () => void;
8 | }
9 |
10 | export const SidebarContext = createContext({
11 | collapsed: false,
12 | setCollapsed: () => {},
13 | });
14 |
15 | export const useSidebarContext = () => {
16 | return useContext(SidebarContext);
17 | };
18 |
--------------------------------------------------------------------------------
/components/navbar/darkmodeswitch.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useTheme as useNextTheme } from "next-themes";
3 | import { Switch } from "@nextui-org/react";
4 |
5 | export const DarkModeSwitch = () => {
6 | const { setTheme, resolvedTheme } = useNextTheme();
7 | return (
8 | setTheme(e ? "dark" : "light")}
11 | />
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/components/navbar/burguer-button.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useSidebarContext } from "../layout/layout-context";
3 | import { StyledBurgerButton } from "./navbar.styles";
4 |
5 | export const BurguerButton = () => {
6 | const { collapsed, setCollapsed } = useSidebarContext();
7 |
8 | return (
9 |
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const { nextui } = require("@nextui-org/react");
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | content: [
6 | "./app/**/*.{js,ts,jsx,tsx,mdx}",
7 | "./pages/**/*.{js,ts,jsx,tsx,mdx}",
8 | "./components/**/*.{js,ts,jsx,tsx,mdx}",
9 |
10 | // Or if using `src` directory:
11 | "./src/**/*.{js,ts,jsx,tsx,mdx}",
12 | "./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}",
13 | ],
14 | theme: {
15 | extend: {},
16 | },
17 | darkMode: "class",
18 | plugins: [nextui()],
19 | };
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 |
16 |
17 | # production
18 | /build
19 |
20 | # misc
21 | .DS_Store
22 | *.pem
23 |
24 | # debug
25 | npm-debug.log*
26 | yarn-debug.log*
27 | yarn-error.log*
28 | .pnpm-debug.log*
29 |
30 | # local env files
31 | .env*.local
32 |
33 | # vercel
34 | .vercel
35 |
36 | # typescript
37 | *.tsbuildinfo
38 | next-env.d.ts
39 | /.github/
--------------------------------------------------------------------------------
/components/icons/sidebar/chevron-up-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | interface Props extends React.SVGAttributes {}
4 |
5 | export const ChevronUpIcon = ({ ...props }: Props) => {
6 | return (
7 |
14 |
18 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/components/icons/sidebar/chevron-down-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | interface Props extends React.SVGAttributes {}
4 | export const ChevronDownIcon = ({ ...props }: Props) => {
5 | return (
6 |
12 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/components/icons/accounts/info-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const InfoIcon = () => {
4 | return (
5 |
12 |
17 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import "@/styles/globals.css";
2 | import type { Metadata } from "next";
3 | import { Providers } from "./providers";
4 | import { fontSans } from "@/config/fonts";
5 | import clsx from "clsx";
6 |
7 | export const metadata: Metadata = {
8 | title: "Next.js",
9 | description: "Generated by Next.js",
10 | };
11 |
12 | export default function RootLayout({
13 | children,
14 | }: {
15 | children: React.ReactNode;
16 | }) {
17 | return (
18 |
19 |
20 | {children}
21 |
22 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/components/icons/sidebar/filter-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const FilterIcon = () => {
4 | return (
5 |
12 |
17 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/components/icons/sidebar/products-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const ProductsIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/icons/sidebar/bottom-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const BottomIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/helpers/schemas.ts:
--------------------------------------------------------------------------------
1 | import { object, ref, string } from "yup";
2 |
3 | export const LoginSchema = object().shape({
4 | email: string()
5 | .email("This field must be an email")
6 | .required("Email is required"),
7 | password: string().required("Password is required"),
8 | });
9 |
10 | export const RegisterSchema = object().shape({
11 | name: string().required("Name is required"),
12 | email: string()
13 | .email("This field must be an email")
14 | .required("Email is required"),
15 | password: string().required("Password is required"),
16 | confirmPassword: string()
17 | .required("Confirm password is required")
18 | .oneOf([ref("password")], "Passwords must match"),
19 | });
20 |
--------------------------------------------------------------------------------
/app/providers.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import * as React from "react";
3 | import { NextUIProvider } from "@nextui-org/system";
4 | import { ThemeProvider as NextThemesProvider } from "next-themes";
5 | import { ThemeProviderProps } from "next-themes/dist/types";
6 |
7 | export interface ProvidersProps {
8 | children: React.ReactNode;
9 | themeProps?: ThemeProviderProps;
10 | }
11 |
12 | export function Providers({ children, themeProps }: ProvidersProps) {
13 | return (
14 |
15 |
19 | {children}
20 |
21 |
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/components/icons/sidebar/accounts-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const AccountsIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/middleware.ts:
--------------------------------------------------------------------------------
1 | import { NextResponse } from "next/server";
2 | import type { NextRequest } from "next/server";
3 |
4 | export function middleware(request: NextRequest) {
5 | const { pathname } = request.nextUrl;
6 |
7 | if (
8 | (pathname === "/login" || pathname === "/register") &&
9 | request.cookies.has("userAuth")
10 | )
11 | return NextResponse.redirect(new URL("/", request.url));
12 |
13 | if (
14 | (pathname === "/" || pathname === "/accounts") &&
15 | !request.cookies.has("userAuth")
16 | )
17 | return NextResponse.redirect(new URL("/login", request.url));
18 |
19 | return NextResponse.next();
20 | }
21 |
22 | export const config = {
23 | matcher: ["/", "/accounts", "/login", "/register"],
24 | };
25 |
--------------------------------------------------------------------------------
/components/icons/acmelogo.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const AcmeLogo = () => (
4 |
12 |
13 |
20 |
21 | );
22 |
--------------------------------------------------------------------------------
/components/icons/accounts/dots-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const DotsIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/icons/accounts/trash-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const TrashIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/icons/sidebar/payments-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const PaymentsIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "strict": true,
12 | "forceConsistentCasingInFileNames": true,
13 | "noEmit": true,
14 | "esModuleInterop": true,
15 | "module": "esnext",
16 | "moduleResolution": "node",
17 | "resolveJsonModule": true,
18 | "isolatedModules": true,
19 | "jsx": "preserve",
20 | "incremental": true,
21 | "plugins": [
22 | {
23 | "name": "next"
24 | }
25 | ],
26 | "paths": {
27 | "@/*": ["./*"]
28 | }
29 | },
30 | "include": [
31 | "next-env.d.ts",
32 | "**/*.ts",
33 | "**/*.tsx",
34 | ".next/types/**/*.ts"
35 | ],
36 | "exclude": [
37 | "node_modules"
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/components/icons/searchicon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const SearchIcon = () => {
4 | return (
5 |
14 |
21 |
28 |
29 | );
30 | };
31 |
--------------------------------------------------------------------------------
/components/icons/sidebar/home-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const HomeIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/icons/breadcrumb/users-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const UsersIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/icons/breadcrumb/house-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const HouseIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/icons/accounts/export-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const ExportIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dashboard",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@nextui-org/react": "2.0.22",
13 | "apexcharts": "^3.35.5",
14 | "clsx": "^2.0.0",
15 | "formik": "^2.4.6",
16 | "framer-motion": "^10.16.0",
17 | "next": "^14.0.4",
18 | "next-themes": "0.2.1",
19 | "react": "18.2.0",
20 | "react-apexcharts": "^1.4.0",
21 | "react-dom": "18.2.0",
22 | "yup": "^1.4.0"
23 | },
24 | "devDependencies": {
25 | "@types/node": "18.7.18",
26 | "@types/react": "18.0.20",
27 | "@types/react-dom": "18.0.6",
28 | "autoprefixer": "^10.4.15",
29 | "eslint": "8.23.1",
30 | "eslint-config-next": "13.4.16",
31 | "postcss": "^8.4.28",
32 | "tailwindcss": "^3.3.3",
33 | "typescript": "4.8.3"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/components/icons/sidebar/view-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const ViewIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/icons/sidebar/balance-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const BalanceIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/icons/sidebar/reports-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const ReportsIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/components/layout/layout.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React from "react";
4 | import { useLockedBody } from "../hooks/useBodyLock";
5 | import { NavbarWrapper } from "../navbar/navbar";
6 | import { SidebarWrapper } from "../sidebar/sidebar";
7 | import { SidebarContext } from "./layout-context";
8 |
9 | interface Props {
10 | children: React.ReactNode;
11 | }
12 |
13 | export const Layout = ({ children }: Props) => {
14 | const [sidebarOpen, setSidebarOpen] = React.useState(false);
15 | const [_, setLocked] = useLockedBody(false);
16 | const handleToggleSidebar = () => {
17 | setSidebarOpen(!sidebarOpen);
18 | setLocked(!sidebarOpen);
19 | };
20 |
21 | return (
22 |
27 |
28 |
29 | {children}
30 |
31 |
32 | );
33 | };
34 |
--------------------------------------------------------------------------------
/components/icons/sidebar/dev-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const DevIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/components/icons/navbar/github-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const GithubIcon = () => {
4 | return (
5 |
6 |
12 |
13 | );
14 | };
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Mauricio Siu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/components/icons/sidebar/customers-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const CustomersIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/sidebar/sidebar-item.tsx:
--------------------------------------------------------------------------------
1 | import NextLink from "next/link";
2 | import React from "react";
3 | import { useSidebarContext } from "../layout/layout-context";
4 | import clsx from "clsx";
5 |
6 | interface Props {
7 | title: string;
8 | icon: React.ReactNode;
9 | isActive?: boolean;
10 | href?: string;
11 | }
12 |
13 | export const SidebarItem = ({ icon, title, isActive, href = "" }: Props) => {
14 | const { collapsed, setCollapsed } = useSidebarContext();
15 |
16 | const handleClick = () => {
17 | if (window.innerWidth < 768) {
18 | setCollapsed();
19 | }
20 | };
21 | return (
22 |
26 |
35 | {icon}
36 | {title}
37 |
38 |
39 | );
40 | };
41 |
--------------------------------------------------------------------------------
/components/icons/navbar/support-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const SupportIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/table/table.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Link,
3 | Table,
4 | TableBody,
5 | TableCell,
6 | TableColumn,
7 | TableHeader,
8 | TableRow,
9 | } from "@nextui-org/react";
10 | import React from "react";
11 | import { columns, users } from "./data";
12 | import { RenderCell } from "./render-cell";
13 |
14 | export const TableWrapper = () => {
15 | return (
16 |
17 |
18 |
19 | {(column) => (
20 |
25 | {column.name}
26 |
27 | )}
28 |
29 |
30 | {(item) => (
31 |
32 | {(columnKey) => (
33 |
34 | {RenderCell({ user: item, columnKey: columnKey })}
35 |
36 | )}
37 |
38 | )}
39 |
40 |
41 |
42 | );
43 | };
44 |
--------------------------------------------------------------------------------
/components/icons/sidebar/changelog-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const ChangeLogIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/icons/table/eye-icon.tsx:
--------------------------------------------------------------------------------
1 | interface Props {
2 | size?: number;
3 | fill?: string;
4 | width?: number;
5 | height?: number;
6 | }
7 |
8 | export const EyeIcon = ({fill, size, height, width, ...props}: Props) => {
9 | return (
10 |
18 |
25 |
32 |
33 | );
34 | };
35 |
--------------------------------------------------------------------------------
/components/navbar/navbar.styles.ts:
--------------------------------------------------------------------------------
1 | import { tv } from "@nextui-org/react";
2 |
3 | // NEEDS TO BE REFACTORED
4 |
5 | export const StyledBurgerButton = tv({
6 | base: "absolute flex flex-col justify-around w-6 h-6 bg-transparent border-none cursor-pointer padding-0 z-[202] focus:outline-none [&_div]:w-6 [&_div]:h-px [&_div]:bg-default-900 [&_div]:rounded-xl [&_div]:transition-all [&_div]:relative [&_div]:origin-[1px] ",
7 |
8 | variants: {
9 | open: {
10 | true: "[&",
11 | },
12 | },
13 | // "",
14 | // "& div": {
15 |
16 | // "&:first-child": {
17 | // transform: "translateY(-4px) rotate(0deg)",
18 | // height: "1px",
19 | // marginTop: "10px",
20 | // },
21 | // "&:nth-child(2)": {
22 | // transform: "translateY(4px) rotate(0deg)",
23 | // height: "1px",
24 | // marginBottom: "10px",
25 | // },
26 | // },
27 | // variants: {
28 | // open: {
29 | // true: {
30 | // "& div": {
31 | // "&:first-child": {
32 | // marginTop: "0px",
33 | // transform: "translateY(1px) rotate(45deg)",
34 | // },
35 | // "&:nth-child(2)": {
36 | // marginBottom: "0px",
37 | // transform: "translateY(4px) rotate(-45deg)",
38 | // },
39 | // },
40 | // },
41 | // },
42 | // },
43 | });
44 |
--------------------------------------------------------------------------------
/components/sidebar/sidebar.styles.ts:
--------------------------------------------------------------------------------
1 | import { tv } from "@nextui-org/react";
2 |
3 | export const SidebarWrapper = tv({
4 | base: "bg-background transition-transform h-full fixed -translate-x-full w-64 shrink-0 z-[202] overflow-y-auto border-r border-divider flex-col py-6 px-3 md:ml-0 md:flex md:static md:h-screen md:translate-x-0 ",
5 |
6 | variants: {
7 | collapsed: {
8 | true: "translate-x-0 ml-0 pt-20 [display:inherit]",
9 | },
10 | },
11 | // ""
12 | // "@md": {
13 | // marginLeft: "0",
14 | // display: "flex",
15 | // position: "static",
16 | // height: "100vh",
17 | // transform: "translateX(0)",
18 | // },
19 | // variants: {
20 | // collapsed: {
21 | // true: {
22 | // display: "inherit",
23 | // marginLeft: "0 ",
24 | // transform: "translateX(0)",
25 | // },
26 | // },
27 | // },
28 | });
29 | export const Overlay = tv({
30 | base: "bg-[rgb(15_23_42/0.3)] fixed inset-0 z-[201] opacity-80 transition-opacity md:hidden md:z-auto md:opacity-100",
31 | });
32 |
33 | export const Header = tv({
34 | base: "flex gap-8 items-center px-6",
35 | });
36 |
37 | export const Body = tv({
38 | base: "flex flex-col gap-6 mt-9 px-2",
39 | });
40 |
41 | export const Footer = tv({
42 | base: "flex items-center justify-center gap-6 pt-16 pb-8 px-8 md:pt-10 md:pb-0",
43 | });
44 |
45 | export const Sidebar = Object.assign(SidebarWrapper, {
46 | Header,
47 | Body,
48 | Overlay,
49 | Footer,
50 | });
51 |
--------------------------------------------------------------------------------
/components/icons/table/edit-icon.tsx:
--------------------------------------------------------------------------------
1 | interface Props {
2 | size?: number;
3 | fill?: string;
4 | width?: number;
5 | height?: number;
6 | }
7 |
8 | export const EditIcon = ({fill, size, height, width, ...props}: Props) => {
9 | return (
10 |
18 |
26 |
34 |
42 |
43 | );
44 | };
45 |
--------------------------------------------------------------------------------
/components/icons/sidebar/settings-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const SettingsIcon = () => {
4 | return (
5 |
12 |
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/components/hooks/useBodyLock.ts:
--------------------------------------------------------------------------------
1 | "use client";
2 | import {useEffect, useState} from 'react';
3 | import {useIsomorphicLayoutEffect} from './useIsomorphicLayoutEffect';
4 |
5 | type ReturnType = [boolean, (locked: boolean) => void];
6 |
7 | export const useLockedBody = (initialLocked = false): ReturnType => {
8 | const [locked, setLocked] = useState(initialLocked);
9 |
10 | // Do the side effect before render
11 | useIsomorphicLayoutEffect(() => {
12 | if (!locked) {
13 | return;
14 | }
15 |
16 | // Save initial body style
17 | const originalOverflow = document.body.style.overflow;
18 | const originalPaddingRight = document.body.style.paddingRight;
19 |
20 | // Lock body scroll
21 | document.body.style.overflow = 'hidden';
22 |
23 | // Get the scrollBar width
24 | const root = document.getElementById('___gatsby'); // or root
25 | const scrollBarWidth = root ? root.offsetWidth - root.scrollWidth : 0;
26 |
27 | // Avoid width reflow
28 | if (scrollBarWidth) {
29 | document.body.style.paddingRight = `${scrollBarWidth}px`;
30 | }
31 |
32 | return () => {
33 | document.body.style.overflow = originalOverflow;
34 |
35 | if (scrollBarWidth) {
36 | document.body.style.paddingRight = originalPaddingRight;
37 | }
38 | };
39 | }, [locked]);
40 |
41 | // Update state if initialValue changes
42 | useEffect(() => {
43 | if (locked !== initialLocked) {
44 | setLocked(initialLocked);
45 | }
46 | // eslint-disable-next-line react-hooks/exhaustive-deps
47 | }, [initialLocked]);
48 |
49 | return [locked, setLocked];
50 | };
51 |
--------------------------------------------------------------------------------
/components/auth/authLayout.tsx:
--------------------------------------------------------------------------------
1 | import { Image } from "@nextui-org/react";
2 | import { Divider } from "@nextui-org/divider";
3 |
4 | interface Props {
5 | children: React.ReactNode;
6 | }
7 |
8 | export const AuthLayoutWrapper = ({ children }: Props) => {
9 | return (
10 |
11 |
12 |
13 |
18 |
19 | {children}
20 |
21 |
22 |
25 |
26 |
27 |
28 |
33 |
34 |
35 |
36 |
NextUI Dashboard Template
37 |
38 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Quasi
39 | possimus voluptate, sapiente assumenda deserunt repellendus,
40 | perferendis odit voluptas hic dolores laborum fugit ut? Architecto
41 | quo ex quidem vitae quae rem.
42 |
43 |
44 |
45 |
46 | );
47 | };
48 |
--------------------------------------------------------------------------------
/components/home/card-agents.tsx:
--------------------------------------------------------------------------------
1 | import { Avatar, AvatarGroup, Card, CardBody } from "@nextui-org/react";
2 | import React from "react";
3 |
4 | const pictureUsers = [
5 | "https://i.pravatar.cc/150?u=a042581f4e29026024d",
6 | "https://i.pravatar.cc/150?u=a042581f4e29026704d",
7 | "https://i.pravatar.cc/150?u=a04258114e29026702d",
8 | "https://i.pravatar.cc/150?u=a048581f4e29026701d",
9 | "https://i.pravatar.cc/150?u=a092581d4ef9026700d",
10 | ];
11 |
12 | export const CardAgents = () => {
13 | return (
14 |
15 |
16 |
17 |
18 |
19 | {" "}
20 | {"⭐"}Agents
21 |
22 |
23 |
24 |
25 |
26 |
27 | Meet your agenda and see their ranks to get the best results
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | );
41 | };
42 |
--------------------------------------------------------------------------------
/components/home/card-balance3.tsx:
--------------------------------------------------------------------------------
1 | import { Card, CardBody } from "@nextui-org/react";
2 | import React from "react";
3 | import { Community } from "../icons/community";
4 |
5 | export const CardBalance3 = () => {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 | Card Insurance
13 | 1311 Cars
14 |
15 |
16 |
17 | $3,910
18 | - 4.5%
19 |
20 |
21 |
22 |
23 | {"↓"}
24 | 100,930
25 |
26 |
USD
27 |
28 |
29 |
30 |
31 | {"↑"}
32 | 4,120
33 |
34 |
USD
35 |
36 |
37 |
38 |
39 | {"⭐"}
40 | 125
41 |
42 |
VIP
43 |
44 |
45 |
46 |
47 | );
48 | };
49 |
--------------------------------------------------------------------------------
/components/home/card-balance1.tsx:
--------------------------------------------------------------------------------
1 | import { Card, CardBody } from "@nextui-org/react";
2 | import React from "react";
3 | import { Community } from "../icons/community";
4 |
5 | export const CardBalance1 = () => {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 | Auto Insurance
13 | 1311 Cars
14 |
15 |
16 |
17 | $45,910
18 | + 4.5%
19 |
20 |
21 |
22 |
23 | {"↓"}
24 | 100,930
25 |
26 |
USD
27 |
28 |
29 |
30 |
31 | {"↑"}
32 | 54,120
33 |
34 |
USD
35 |
36 |
37 |
38 |
39 | {"⭐"}
40 | 125
41 |
42 |
VIP
43 |
44 |
45 |
46 |
47 | );
48 | };
49 |
--------------------------------------------------------------------------------
/components/accounts/add-user.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Button,
3 | Input,
4 | Modal,
5 | ModalBody,
6 | ModalContent,
7 | ModalFooter,
8 | ModalHeader,
9 | useDisclosure,
10 | } from "@nextui-org/react";
11 | import React from "react";
12 |
13 | export const AddUser = () => {
14 | const { isOpen, onOpen, onOpenChange } = useDisclosure();
15 |
16 | return (
17 |
18 | <>
19 |
20 | Add User
21 |
22 |
27 |
28 | {(onClose) => (
29 | <>
30 |
31 | Add User
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
45 |
46 |
47 |
48 | Close
49 |
50 |
51 | Add User
52 |
53 |
54 | >
55 | )}
56 |
57 |
58 | >
59 |
60 | );
61 | };
62 |
--------------------------------------------------------------------------------
/components/icons/navbar/notificationicon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const NotificationIcon = () => {
4 | return (
5 |
13 |
19 |
20 |
24 |
25 | );
26 | };
27 |
--------------------------------------------------------------------------------
/components/navbar/notifications-dropdown.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Dropdown,
3 | DropdownItem,
4 | DropdownMenu,
5 | DropdownSection,
6 | DropdownTrigger,
7 | NavbarItem,
8 | } from "@nextui-org/react";
9 | import React from "react";
10 | import { NotificationIcon } from "../icons/navbar/notificationicon";
11 |
12 | export const NotificationsDropdown = () => {
13 | return (
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
30 | 📣 Edit your information
31 |
32 |
40 | 🚀 Say goodbye to paper receipts!
41 |
42 |
50 | 📣 Edit your information
51 |
52 |
53 |
54 |
55 | );
56 | };
57 |
--------------------------------------------------------------------------------
/components/icons/table/delete-icon.tsx:
--------------------------------------------------------------------------------
1 | interface Props {
2 | size?: number;
3 | fill?: string;
4 | width?: number;
5 | height?: number;
6 | }
7 | export const DeleteIcon = ({fill, size, height, width, ...props}: Props) => {
8 | return (
9 |
17 |
24 |
31 |
38 |
45 |
52 |
53 | );
54 | };
55 |
--------------------------------------------------------------------------------
/components/home/card-balance2.tsx:
--------------------------------------------------------------------------------
1 | import { Card, CardBody } from "@nextui-org/react";
2 | import React from "react";
3 | import { Community } from "../icons/community";
4 |
5 | export const CardBalance2 = () => {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 | Health Insurance
13 | +2400 People
14 |
15 |
16 |
17 |
18 | $12,138
19 |
20 | - 4.5%
21 |
22 |
23 |
24 |
25 |
26 | {"↓"}
27 |
28 | 11,930
29 |
30 |
USD
31 |
32 |
33 |
34 |
35 | {"↑"}
36 | 54,120
37 |
38 |
USD
39 |
40 |
41 |
42 |
43 | {"⭐"}
44 | 150
45 |
46 |
VIP
47 |
48 |
49 |
50 |
51 | );
52 | };
53 |
--------------------------------------------------------------------------------
/components/charts/steam.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Chart, { Props } from "react-apexcharts";
3 |
4 | const state: Props["series"] = [
5 | {
6 | name: "Series1",
7 | data: [31, 40, 28, 51, 42, 109, 100],
8 | },
9 | {
10 | name: "Series2",
11 | data: [11, 32, 45, 32, 34, 52, 41],
12 | },
13 | ];
14 |
15 | const options: Props["options"] = {
16 | chart: {
17 | type: "area",
18 | animations: {
19 | easing: "linear",
20 | speed: 300,
21 | },
22 | sparkline: {
23 | enabled: false,
24 | },
25 | brush: {
26 | enabled: false,
27 | },
28 | id: "basic-bar",
29 | foreColor: "hsl(var(--nextui-default-800))",
30 | stacked: true,
31 | toolbar: {
32 | show: false,
33 | },
34 | },
35 |
36 | xaxis: {
37 | categories: [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999],
38 | labels: {
39 | // show: false,
40 | style: {
41 | colors: "hsl(var(--nextui-default-800))",
42 | },
43 | },
44 | axisBorder: {
45 | color: "hsl(var(--nextui-nextui-default-200))",
46 | },
47 | axisTicks: {
48 | color: "hsl(var(--nextui-nextui-default-200))",
49 | },
50 | },
51 | yaxis: {
52 | labels: {
53 | style: {
54 | // hsl(var(--nextui-content1-foreground))
55 | colors: "hsl(var(--nextui-default-800))",
56 | },
57 | },
58 | },
59 | tooltip: {
60 | enabled: false,
61 | },
62 | grid: {
63 | show: true,
64 | borderColor: "hsl(var(--nextui-default-200))",
65 | strokeDashArray: 0,
66 | position: "back",
67 | },
68 | stroke: {
69 | curve: "smooth",
70 | fill: {
71 | colors: ["red"],
72 | },
73 | },
74 | // @ts-ignore
75 | markers: false,
76 | };
77 |
78 | export const Steam = () => {
79 | return (
80 | <>
81 |
86 | >
87 | );
88 | };
89 |
--------------------------------------------------------------------------------
/components/navbar/user-dropdown.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Avatar,
3 | Dropdown,
4 | DropdownItem,
5 | DropdownMenu,
6 | DropdownTrigger,
7 | Navbar,
8 | NavbarItem,
9 | } from "@nextui-org/react";
10 | import React, { useCallback } from "react";
11 | import { DarkModeSwitch } from "./darkmodeswitch";
12 | import { useRouter } from "next/navigation";
13 | import { deleteAuthCookie } from "@/actions/auth.action";
14 |
15 | export const UserDropdown = () => {
16 | const router = useRouter();
17 |
18 | const handleLogout = useCallback(async () => {
19 | await deleteAuthCookie();
20 | router.replace("/login");
21 | }, [router]);
22 |
23 | return (
24 |
25 |
26 |
27 |
33 |
34 |
35 | console.log({ actionKey })}>
38 |
41 | Signed in as
42 | zoey@example.com
43 |
44 | My Settings
45 | Team Settings
46 | Analytics
47 | System
48 | Configurations
49 | Help & Feedback
50 |
55 | Log Out
56 |
57 |
58 |
59 |
60 |
61 |
62 | );
63 | };
64 |
--------------------------------------------------------------------------------
/components/icons/navbar/feedback-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const FeedbackIcon = () => {
4 | return (
5 |
12 |
17 |
22 |
27 |
32 |
37 |
38 | );
39 | };
40 |
--------------------------------------------------------------------------------
/components/navbar/navbar.tsx:
--------------------------------------------------------------------------------
1 | import { Input, Link, Navbar, NavbarContent } from "@nextui-org/react";
2 | import React from "react";
3 | import { FeedbackIcon } from "../icons/navbar/feedback-icon";
4 | import { GithubIcon } from "../icons/navbar/github-icon";
5 | import { SupportIcon } from "../icons/navbar/support-icon";
6 | import { SearchIcon } from "../icons/searchicon";
7 | import { BurguerButton } from "./burguer-button";
8 | import { NotificationsDropdown } from "./notifications-dropdown";
9 | import { UserDropdown } from "./user-dropdown";
10 |
11 | interface Props {
12 | children: React.ReactNode;
13 | }
14 |
15 | export const NavbarWrapper = ({ children }: Props) => {
16 | return (
17 |
18 |
25 |
26 |
27 |
28 |
29 | }
31 | isClearable
32 | className="w-full"
33 | classNames={{
34 | input: "w-full",
35 | mainWrapper: "w-full",
36 | }}
37 | placeholder="Search..."
38 | />
39 |
40 |
44 |
45 |
46 | Feedback?
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | {children}
67 |
68 | );
69 | };
70 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NextJS and NextUI Dashboard Template Starter
2 |
3 | You can deploy here directly to vercel [](https://vercel.com/import/project?template=https://github.com/Siumauricio/nextui-dashboard-template)
4 |
5 |
6 | V1 Version Stitches https://v1-nextui-dashboard-template.vercel.app/
7 | V1 Code: https://github.com/Siumauricio/nextui-dashboard-template/tree/v1
8 |
9 | This is a template for NextJS and NextUI.
10 |
11 | [NextJS](https://nextjs.org/)
12 | [NextUI](https://nextui.org/)
13 |
14 | You can see the demo here: https://nextui-dashboard-template.vercel.app/
15 | For improve this template, you can create a pull request or open an issue here [Issues](https://github.com/Siumauricio/nextui-dashboard-template/issues) or [Pull Request](
16 | https://github.com/Siumauricio/nextui-dashboard-template/pulls)
17 |
18 | ### Dark Mode
19 | 
20 |
21 | ### Light Mode
22 | 
23 |
24 |
25 | - Dark Mode Support
26 | - Full Responsive
27 | - Home Page with Charts
28 | - Accounts Page
29 | - More pages coming soon...
30 |
31 | ```
32 | ├── components
33 | │ ├── accounts # Accounts components
34 | │ ├── charts # Charts components
35 | │ ├── breadcrumb # component
36 | | ├── home # Home components
37 | | ├── layout # Layout components
38 | | ├── navbar # Navbar components
39 | | ├── sidebar # Sidebar components
40 | | ├── table # Table components
41 | | ├── styles # Some reusable components
42 | | ├── icons # Icons
43 | | ├── hooks # Hooks
44 | ├── app # Documentation files
45 | │ ├── accounts # Accounts route
46 | | ├── page.tsx # Accounts page
47 | │ ├── page.tsx # Entry point for the app
48 | │ ├── layout.tsx # Layout applied to all application pages
49 | │ ├── providers.tsx # Theme provider
50 | │ ├── more... # Soon
51 | └──
52 | ```
53 |
54 | ## For Run
55 |
56 | Install dependencies
57 |
58 |
59 | ```bash
60 | npm install
61 | ```
62 |
63 | Start the server
64 |
65 |
66 |
67 | ```bash
68 | npm run dev
69 | ```
70 |
71 | Now you can visit https://localhost:3000 in your browser.
72 |
--------------------------------------------------------------------------------
/components/accounts/index.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { Button, Input } from "@nextui-org/react";
3 | import Link from "next/link";
4 | import React from "react";
5 | import { DotsIcon } from "@/components/icons/accounts/dots-icon";
6 | import { ExportIcon } from "@/components/icons/accounts/export-icon";
7 | import { InfoIcon } from "@/components/icons/accounts/info-icon";
8 | import { TrashIcon } from "@/components/icons/accounts/trash-icon";
9 | import { HouseIcon } from "@/components/icons/breadcrumb/house-icon";
10 | import { UsersIcon } from "@/components/icons/breadcrumb/users-icon";
11 | import { SettingsIcon } from "@/components/icons/sidebar/settings-icon";
12 | import { TableWrapper } from "@/components/table/table";
13 | import { AddUser } from "./add-user";
14 |
15 | export const Accounts = () => {
16 | return (
17 |
18 |
19 |
20 |
21 |
22 | Home
23 |
24 | / {" "}
25 |
26 |
27 |
28 |
29 | Users
30 | / {" "}
31 |
32 |
33 | List
34 |
35 |
36 |
37 |
All Accounts
38 |
39 |
40 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
}>
55 | Export to CSV
56 |
57 |
58 |
59 |
62 |
63 | );
64 | };
65 |
--------------------------------------------------------------------------------
/components/home/card-transactions.tsx:
--------------------------------------------------------------------------------
1 | import { Avatar, Card, CardBody } from "@nextui-org/react";
2 | import React from "react";
3 |
4 | const items = [
5 | {
6 | name: "Jose Perez",
7 | picture: "https://i.pravatar.cc/150?u=a042581f4e29026024d",
8 | amount: "4500 USD",
9 | date: "9/20/2021",
10 | },
11 | {
12 | name: "Jose Perez",
13 | picture: "https://i.pravatar.cc/150?u=a042581f4e29026024d",
14 | amount: "4500 USD",
15 | date: "9/20/2021",
16 | },
17 | {
18 | name: "Jose Perez",
19 | picture: "https://i.pravatar.cc/150?u=a042581f4e29026024d",
20 | amount: "4500 USD",
21 | date: "9/20/2021",
22 | },
23 | {
24 | name: "Jose Perez",
25 | picture: "https://i.pravatar.cc/150?u=a042581f4e29026024d",
26 | amount: "4500 USD",
27 | date: "9/20/2021",
28 | },
29 | {
30 | name: "Jose Perez",
31 | picture: "https://i.pravatar.cc/150?u=a042581f4e29026024d",
32 | amount: "4500 USD",
33 | date: "9/20/2021",
34 | },
35 | ];
36 |
37 | export const CardTransactions = () => {
38 | return (
39 |
40 |
41 |
42 |
43 |
44 | Latest Transactions
45 |
46 |
47 |
48 |
49 |
50 | {items.map((item) => (
51 |
52 |
59 |
60 |
61 | {item.name}
62 |
63 |
64 | {item.amount}
65 |
66 |
67 | {item.date}
68 |
69 |
70 | ))}
71 |
72 |
73 |
74 | );
75 | };
76 |
--------------------------------------------------------------------------------
/components/auth/login.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { createAuthCookie } from "@/actions/auth.action";
4 | import { LoginSchema } from "@/helpers/schemas";
5 | import { LoginFormType } from "@/helpers/types";
6 | import { Button, Input } from "@nextui-org/react";
7 | import { Formik } from "formik";
8 | import Link from "next/link";
9 | import { useRouter } from "next/navigation";
10 | import { useCallback } from "react";
11 |
12 | export const Login = () => {
13 | const router = useRouter();
14 |
15 | const initialValues: LoginFormType = {
16 | email: "admin@acme.com",
17 | password: "admin",
18 | };
19 |
20 | const handleLogin = useCallback(
21 | async (values: LoginFormType) => {
22 | // `values` contains email & password. You can use provider to connect user
23 |
24 | await createAuthCookie();
25 | router.replace("/");
26 | },
27 | [router]
28 | );
29 |
30 | return (
31 | <>
32 | Login
33 |
34 |
38 | {({ values, errors, touched, handleChange, handleSubmit }) => (
39 | <>
40 |
41 |
50 |
59 |
60 |
61 | handleSubmit()}
63 | variant='flat'
64 | color='primary'>
65 | Login
66 |
67 | >
68 | )}
69 |
70 |
71 |
72 | Don't have an account ?{" "}
73 |
74 | Register here
75 |
76 |
77 | >
78 | );
79 | };
80 |
--------------------------------------------------------------------------------
/components/home/content.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React from "react";
3 | import dynamic from "next/dynamic";
4 | import { TableWrapper } from "../table/table";
5 | import { CardBalance1 } from "./card-balance1";
6 | import { CardBalance2 } from "./card-balance2";
7 | import { CardBalance3 } from "./card-balance3";
8 | import { CardAgents } from "./card-agents";
9 | import { CardTransactions } from "./card-transactions";
10 | import { Link } from "@nextui-org/react";
11 | import NextLink from "next/link";
12 |
13 | const Chart = dynamic(
14 | () => import("../charts/steam").then((mod) => mod.Steam),
15 | {
16 | ssr: false,
17 | }
18 | );
19 |
20 | export const Content = () => (
21 |
22 |
23 |
24 | {/* Card Section Top */}
25 |
26 |
Available Balance
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | {/* Chart */}
35 |
36 |
Statistics
37 |
38 |
39 |
40 |
41 |
42 |
43 | {/* Left Section */}
44 |
45 |
Section
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | {/* Table Latest Users */}
54 |
55 |
56 |
Latest Users
57 |
63 | View All
64 |
65 |
66 |
67 |
68 |
69 | );
70 |
--------------------------------------------------------------------------------
/components/table/render-cell.tsx:
--------------------------------------------------------------------------------
1 | import { User, Tooltip, Chip } from "@nextui-org/react";
2 | import React from "react";
3 | import { DeleteIcon } from "../icons/table/delete-icon";
4 | import { EditIcon } from "../icons/table/edit-icon";
5 | import { EyeIcon } from "../icons/table/eye-icon";
6 | import { users } from "./data";
7 |
8 | interface Props {
9 | user: (typeof users)[number];
10 | columnKey: string | React.Key;
11 | }
12 |
13 | export const RenderCell = ({ user, columnKey }: Props) => {
14 | // @ts-ignore
15 | const cellValue = user[columnKey];
16 | switch (columnKey) {
17 | case "name":
18 | return (
19 |
25 | {user.email}
26 |
27 | );
28 | case "role":
29 | return (
30 |
31 |
32 | {cellValue}
33 |
34 |
35 | {user.team}
36 |
37 |
38 | );
39 | case "status":
40 | return (
41 |
52 | {cellValue}
53 |
54 | );
55 |
56 | case "actions":
57 | return (
58 |
59 |
60 |
61 | console.log("View user", user.id)}>
62 |
63 |
64 |
65 |
66 |
67 |
68 | console.log("Edit user", user.id)}>
69 |
70 |
71 |
72 |
73 |
74 | console.log("Delete user", user.id)}
78 | >
79 |
80 |
81 |
82 |
83 |
84 |
85 | );
86 | default:
87 | return cellValue;
88 | }
89 | };
90 |
--------------------------------------------------------------------------------
/components/auth/register.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { createAuthCookie } from "@/actions/auth.action";
4 | import { RegisterSchema } from "@/helpers/schemas";
5 | import { RegisterFormType } from "@/helpers/types";
6 | import { Button, Input } from "@nextui-org/react";
7 | import { Formik } from "formik";
8 | import Link from "next/link";
9 | import { useRouter } from "next/navigation";
10 | import { useCallback } from "react";
11 |
12 | export const Register = () => {
13 | const router = useRouter();
14 |
15 | const initialValues: RegisterFormType = {
16 | name: "Acme",
17 | email: "admin@acme.com",
18 | password: "admin",
19 | confirmPassword: "admin",
20 | };
21 |
22 | const handleRegister = useCallback(
23 | async (values: RegisterFormType) => {
24 | // `values` contains name, email & password. You can use provider to register user
25 |
26 | await createAuthCookie();
27 | router.replace("/");
28 | },
29 | [router]
30 | );
31 |
32 | return (
33 | <>
34 | Register
35 |
36 |
40 | {({ values, errors, touched, handleChange, handleSubmit }) => (
41 | <>
42 |
43 |
51 |
60 |
69 |
80 |
81 |
82 | handleSubmit()}
84 | variant='flat'
85 | color='primary'>
86 | Register
87 |
88 | >
89 | )}
90 |
91 |
92 |
93 | Already have an account ?{" "}
94 |
95 | Login here
96 |
97 |
98 | >
99 | );
100 | };
101 |
--------------------------------------------------------------------------------
/components/icons/community.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | interface Props {
4 | color?: string;
5 | }
6 |
7 | export const Community = ({ color = "white" }: Props) => {
8 | return (
9 |
16 |
23 |
24 | );
25 | };
26 |
--------------------------------------------------------------------------------
/components/sidebar/companies-dropdown.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import {
3 | Dropdown,
4 | DropdownItem,
5 | DropdownMenu,
6 | DropdownSection,
7 | DropdownTrigger,
8 | } from "@nextui-org/react";
9 | import React, { useState } from "react";
10 | import { AcmeIcon } from "../icons/acme-icon";
11 | import { AcmeLogo } from "../icons/acmelogo";
12 | import { BottomIcon } from "../icons/sidebar/bottom-icon";
13 |
14 | interface Company {
15 | name: string;
16 | location: string;
17 | logo: React.ReactNode;
18 | }
19 |
20 | export const CompaniesDropdown = () => {
21 | const [company, setCompany] = useState({
22 | name: "Acme Co.",
23 | location: "Palo Alto, CA",
24 | logo: ,
25 | });
26 | return (
27 |
32 |
33 |
34 | {company.logo}
35 |
36 |
37 | {company.name}
38 |
39 |
40 | {company.location}
41 |
42 |
43 |
44 |
45 |
46 | {
48 | if (e === "1") {
49 | setCompany({
50 | name: "Facebook",
51 | location: "San Fransico, CA",
52 | logo: ,
53 | });
54 | }
55 | if (e === "2") {
56 | setCompany({
57 | name: "Instagram",
58 | location: "Austin, Tx",
59 | logo: ,
60 | });
61 | }
62 | if (e === "3") {
63 | setCompany({
64 | name: "Twitter",
65 | location: "Brooklyn, NY",
66 | logo: ,
67 | });
68 | }
69 | if (e === "4") {
70 | setCompany({
71 | name: "Acme Co.",
72 | location: "Palo Alto, CA",
73 | logo: ,
74 | });
75 | }
76 | }}
77 | aria-label="Avatar Actions"
78 | >
79 |
80 | }
83 | description="San Fransico, CA"
84 | classNames={{
85 | base: "py-4",
86 | title: "text-base font-semibold",
87 | }}
88 | >
89 | Facebook
90 |
91 | }
94 | description="Austin, Tx"
95 | classNames={{
96 | base: "py-4",
97 | title: "text-base font-semibold",
98 | }}
99 | >
100 | Instagram
101 |
102 | }
105 | description="Brooklyn, NY"
106 | classNames={{
107 | base: "py-4",
108 | title: "text-base font-semibold",
109 | }}
110 | >
111 | Twitter
112 |
113 | }
116 | description="Palo Alto, CA"
117 | classNames={{
118 | base: "py-4",
119 | title: "text-base font-semibold",
120 | }}
121 | >
122 | Acme Co.
123 |
124 |
125 |
126 |
127 | );
128 | };
129 |
--------------------------------------------------------------------------------
/components/sidebar/collapse-items.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React, { useState } from "react";
3 | import { ChevronDownIcon } from "../icons/sidebar/chevron-down-icon";
4 | import { Accordion, AccordionItem } from "@nextui-org/react";
5 | import clsx from "clsx";
6 |
7 | interface Props {
8 | icon: React.ReactNode;
9 | title: string;
10 | items: string[];
11 | }
12 |
13 | export const CollapseItems = ({ icon, items, title }: Props) => {
14 | const [open, setOpen] = useState(false);
15 |
16 | return (
17 |
18 |
19 | }
21 | classNames={{
22 | indicator: "data-[open=true]:-rotate-180",
23 | trigger:
24 | "py-0 min-h-[44px] hover:bg-default-100 rounded-xl active:scale-[0.98] transition-transform px-3.5",
25 |
26 | title:
27 | "px-0 flex text-base gap-2 h-full items-center cursor-pointer",
28 | }}
29 | aria-label="Accordion 1"
30 | title={
31 |
32 | {icon}
33 | {title}
34 |
35 | }
36 | >
37 |
38 | {items.map((item, index) => (
39 |
43 | {item}
44 |
45 | ))}
46 |
47 |
48 |
49 | {/*
70 |
71 | {icon}
72 |
81 | {title}
82 |
83 |
84 |
85 |
95 |
96 | }
97 | // css={{
98 | // width: "100%",
99 | // "& .nextui-collapse-view": {
100 | // p: "0",
101 | // },
102 | // "& .nextui-collapse-content": {
103 | // marginTop: "$1",
104 | // padding: "0px",
105 | // },
106 | // }}
107 | divider={false}
108 | showArrow={false}
109 | >
110 | {items.map((item, index) => (
111 |
119 |
132 | {item}
133 |
134 |
135 | ))}
136 | */}
137 |
138 | );
139 | };
140 |
--------------------------------------------------------------------------------
/components/table/data.ts:
--------------------------------------------------------------------------------
1 | export const columns = [
2 | {name: 'NAME', uid: 'name'},
3 | {name: 'ROLE', uid: 'role'},
4 | {name: 'STATUS', uid: 'status'},
5 | {name: 'ACTIONS', uid: 'actions'},
6 | ];
7 | export const users = [
8 | {
9 | id: 1,
10 | name: 'Tony Reichert',
11 | role: 'CEO',
12 | team: 'Management',
13 | status: 'active',
14 | age: '29',
15 | avatar: 'https://i.pravatar.cc/150?u=a042581f4e29026024d',
16 | email: 'tony.reichert@example.com',
17 | },
18 | {
19 | id: 2,
20 | name: 'Zoey Lang',
21 | role: 'Technical Lead',
22 | team: 'Development',
23 | status: 'paused',
24 | age: '25',
25 | avatar: 'https://i.pravatar.cc/150?u=a042581f4e29026704d',
26 | email: 'zoey.lang@example.com',
27 | },
28 | {
29 | id: 3,
30 | name: 'Jane Fisher',
31 | role: 'Senior Developer',
32 | team: 'Development',
33 | status: 'active',
34 | age: '22',
35 | avatar: 'https://i.pravatar.cc/150?u=a04258114e29026702d',
36 | email: 'jane.fisher@example.com',
37 | },
38 | {
39 | id: 4,
40 | name: 'William Howard',
41 | role: 'Community Manager',
42 | team: 'Marketing',
43 | status: 'vacation',
44 | age: '28',
45 | avatar: 'https://i.pravatar.cc/150?u=a048581f4e29026701d',
46 | email: 'william.howard@example.com',
47 | },
48 | {
49 | id: 5,
50 | name: 'Kristen Copper',
51 | role: 'Sales Manager',
52 | team: 'Sales',
53 | status: 'active',
54 | age: '24',
55 | avatar: 'https://i.pravatar.cc/150?u=a092581d4ef9026700d',
56 | email: 'kristen.cooper@example.com',
57 | },
58 | {
59 | id: 6,
60 | name: 'Tony Reichert',
61 | role: 'CEO',
62 | team: 'Management',
63 | status: 'active',
64 | age: '29',
65 | avatar: 'https://i.pravatar.cc/150?u=a042581f4e29026024d',
66 | email: 'tony.reichert@example.com',
67 | },
68 | {
69 | id: 10,
70 | name: 'Kristen Copper',
71 | role: 'Sales Manager',
72 | team: 'Sales',
73 | status: 'active',
74 | age: '24',
75 | avatar: 'https://i.pravatar.cc/150?u=a092581d4ef9026700d',
76 | email: 'kristen.cooper@example.com',
77 | },
78 | {
79 | id: 8,
80 | name: 'Jane Fisher',
81 | role: 'Senior Developer',
82 | team: 'Development',
83 | status: 'active',
84 | age: '22',
85 | avatar: 'https://i.pravatar.cc/150?u=a04258114e29026702d',
86 | email: 'jane.fisher@example.com',
87 | },
88 | {
89 | id: 7,
90 | name: 'Zoey Lang',
91 | role: 'Technical Lead',
92 | team: 'Development',
93 | status: 'paused',
94 | age: '25',
95 | avatar: 'https://i.pravatar.cc/150?u=a042581f4e29026704d',
96 | email: 'zoey.lang@example.com',
97 | },
98 |
99 | {
100 | id: 9,
101 | name: 'William Howard',
102 | role: 'Community Manager',
103 | team: 'Marketing',
104 | status: 'vacation',
105 | age: '28',
106 | avatar: 'https://i.pravatar.cc/150?u=a048581f4e29026701d',
107 | email: 'william.howard@example.com',
108 | },
109 | {
110 | id: 11,
111 | name: 'Tony Reichert',
112 | role: 'CEO',
113 | team: 'Management',
114 | status: 'active',
115 | age: '29',
116 | avatar: 'https://i.pravatar.cc/150?u=a042581f4e29026024d',
117 | email: 'tony.reichert@example.com',
118 | },
119 | {
120 | id: 12,
121 | name: 'Kristen Copper',
122 | role: 'Sales Manager',
123 | team: 'Sales',
124 | status: 'active',
125 | age: '24',
126 | avatar: 'https://i.pravatar.cc/150?u=a092581d4ef9026700d',
127 | email: 'kristen.cooper@example.com',
128 | },
129 | {
130 | id: 13,
131 | name: 'Jane Fisher',
132 | role: 'Senior Developer',
133 | team: 'Development',
134 | status: 'active',
135 | age: '22',
136 | avatar: 'https://i.pravatar.cc/150?u=a04258114e29026702d',
137 | email: 'jane.fisher@example.com',
138 | },
139 | {
140 | id: 14,
141 | name: 'Zoey Lang',
142 | role: 'Technical Lead',
143 | team: 'Development',
144 | status: 'paused',
145 | age: '25',
146 | avatar: 'https://i.pravatar.cc/150?u=a042581f4e29026704d',
147 | email: 'zoey.lang@example.com',
148 | },
149 | {
150 | id: 15,
151 | name: 'Tony Reichert',
152 | role: 'CEO',
153 | team: 'Management',
154 | status: 'active',
155 | age: '29',
156 | avatar: 'https://i.pravatar.cc/150?u=a042581f4e29026024d',
157 | email: 'tony.reichert@example.com',
158 | },
159 | {
160 | id: 16,
161 | name: 'Kristen Copper',
162 | role: 'Sales Manager',
163 | team: 'Sales',
164 | status: 'active',
165 | age: '24',
166 | avatar: 'https://i.pravatar.cc/150?u=a092581d4ef9026700d',
167 | email: 'kristen.cooper@example.com',
168 | },
169 | ];
170 |
--------------------------------------------------------------------------------
/components/icons/acme-icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const AcmeIcon = () => {
4 | return (
5 |
13 |
21 |
28 |
29 | );
30 | };
31 |
--------------------------------------------------------------------------------
/components/sidebar/sidebar.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Sidebar } from "./sidebar.styles";
3 | import { Avatar, Tooltip } from "@nextui-org/react";
4 | import { CompaniesDropdown } from "./companies-dropdown";
5 | import { HomeIcon } from "../icons/sidebar/home-icon";
6 | import { PaymentsIcon } from "../icons/sidebar/payments-icon";
7 | import { BalanceIcon } from "../icons/sidebar/balance-icon";
8 | import { AccountsIcon } from "../icons/sidebar/accounts-icon";
9 | import { CustomersIcon } from "../icons/sidebar/customers-icon";
10 | import { ProductsIcon } from "../icons/sidebar/products-icon";
11 | import { ReportsIcon } from "../icons/sidebar/reports-icon";
12 | import { DevIcon } from "../icons/sidebar/dev-icon";
13 | import { ViewIcon } from "../icons/sidebar/view-icon";
14 | import { SettingsIcon } from "../icons/sidebar/settings-icon";
15 | import { CollapseItems } from "./collapse-items";
16 | import { SidebarItem } from "./sidebar-item";
17 | import { SidebarMenu } from "./sidebar-menu";
18 | import { FilterIcon } from "../icons/sidebar/filter-icon";
19 | import { useSidebarContext } from "../layout/layout-context";
20 | import { ChangeLogIcon } from "../icons/sidebar/changelog-icon";
21 | import { usePathname } from "next/navigation";
22 |
23 | export const SidebarWrapper = () => {
24 | const pathname = usePathname();
25 | const { collapsed, setCollapsed } = useSidebarContext();
26 |
27 | return (
28 |
29 | {collapsed ? (
30 |
31 | ) : null}
32 |
37 |
38 |
39 |
40 |
41 |
42 | }
45 | isActive={pathname === "/"}
46 | href="/"
47 | />
48 |
49 | }
53 | href="accounts"
54 | />
55 | }
59 | />
60 | }
62 | items={["Banks Accounts", "Credit Cards", "Loans"]}
63 | title="Balances"
64 | />
65 | }
69 | />
70 | }
74 | />
75 | }
79 | />
80 |
81 |
82 |
83 | }
87 | />
88 | }
92 | />
93 | }
97 | />
98 |
99 |
100 |
101 | }
105 | />
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
124 |
125 |
126 |
127 |
128 |
129 | );
130 | };
131 |
--------------------------------------------------------------------------------