diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml
index b0680587b..eca85b3e7 100644
--- a/.github/workflows/prod.yml
+++ b/.github/workflows/prod.yml
@@ -31,7 +31,7 @@ jobs:
run: |
cd vite
corepack enable
- yarn set version 4.10.3
+ yarn set version 4.17.1
yarn
yarn build
diff --git a/next/.env b/next/.env
new file mode 100644
index 000000000..86f1ef4b3
--- /dev/null
+++ b/next/.env
@@ -0,0 +1,5 @@
+NEXT_PUBLIC_VERSION=v5.2.0
+GENERATE_SOURCEMAP=false
+
+## Backend API URL
+NEXT_PUBLIC_API_URL=https://mock-data-api-nextjs.vercel.app/
\ No newline at end of file
diff --git a/next/.gitignore b/next/.gitignore
new file mode 100644
index 000000000..d32ba23b7
--- /dev/null
+++ b/next/.gitignore
@@ -0,0 +1,43 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.*
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/sdks
+!.yarn/versions
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+.pnpm-debug.log*
+
+# local env files
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# vercel
+.vercel
+
+!package-lock.json
diff --git a/next/.prettierignore b/next/.prettierignore
new file mode 100644
index 000000000..db5ddae55
--- /dev/null
+++ b/next/.prettierignore
@@ -0,0 +1,2 @@
+.next
+node_modules
\ No newline at end of file
diff --git a/next/.prettierrc b/next/.prettierrc
new file mode 100644
index 000000000..b5cde330e
--- /dev/null
+++ b/next/.prettierrc
@@ -0,0 +1,9 @@
+{
+ "bracketSpacing": true,
+ "printWidth": 140,
+ "singleQuote": true,
+ "trailingComma": "none",
+ "tabWidth": 2,
+ "useTabs": false,
+ "endOfLine": "lf"
+}
diff --git a/next/.yarnrc.yml b/next/.yarnrc.yml
new file mode 100644
index 000000000..3186f3f07
--- /dev/null
+++ b/next/.yarnrc.yml
@@ -0,0 +1 @@
+nodeLinker: node-modules
diff --git a/next/eslint.config.mjs b/next/eslint.config.mjs
new file mode 100644
index 000000000..7b3c8f447
--- /dev/null
+++ b/next/eslint.config.mjs
@@ -0,0 +1,89 @@
+import eslint from '@eslint/js';
+import { defineConfig, globalIgnores } from 'eslint/config';
+import nextPlugin from '@next/eslint-plugin-next';
+import reactHooks from 'eslint-plugin-react-hooks';
+import prettier from 'eslint-config-prettier/flat';
+import prettierPlugin from 'eslint-plugin-prettier';
+import globals from 'globals';
+
+// ESLint 10 flat config.
+// eslint-config-next is intentionally not used: the plugins it bundles
+// (eslint-plugin-react / import / jsx-a11y) have no ESLint 10 compatible
+// release yet. We compose the pieces that do support ESLint 10 directly:
+// the Next.js plugin (core-web-vitals rules) and react-hooks.
+export default defineConfig([
+ eslint.configs.recommended,
+
+ // Next.js core-web-vitals rules (registers the @next/next plugin)
+ nextPlugin.configs['core-web-vitals'],
+
+ // React Hooks recommended (ESLint 10 compatible flat config)
+ reactHooks.configs.flat['recommended-latest'],
+
+ {
+ files: ['**/*.{js,jsx,mjs}'],
+
+ plugins: {
+ prettier: prettierPlugin
+ },
+
+ languageOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ parserOptions: {
+ ecmaFeatures: { jsx: true }
+ },
+ globals: {
+ ...globals.browser,
+ ...globals.node,
+ ...globals.es2021
+ }
+ },
+
+ rules: {
+ // --- Core rule preferences ---
+ 'no-param-reassign': 'off',
+ 'no-console': 'off',
+ 'no-shadow': 'off',
+ 'prefer-destructuring': 'off',
+
+ // --- React Hooks: silence the noisy new (v7) rules ---
+ 'react-hooks/purity': 'off',
+ 'react-hooks/refs': 'off',
+ 'react-hooks/set-state-in-effect': 'off',
+ 'react-hooks/immutability': 'off',
+ 'react-hooks/static-components': 'off',
+
+ // --- New in ESLint 10 `recommended`: noisy on default-init idioms
+ // (e.g. `let x = ; if (…) x = …`), keep it off ---
+ 'no-useless-assignment': 'off',
+
+ // --- Project-specific restrictions ---
+ 'no-restricted-imports': [
+ 'error',
+ {
+ patterns: ['@mui/*/*/*', '!@mui/material/test-utils/*']
+ }
+ ],
+
+ 'no-unused-vars': [
+ 'error',
+ {
+ vars: 'all',
+ args: 'none',
+ // allow `const { omit, ...rest } = obj` to intentionally drop props
+ ignoreRestSiblings: true
+ }
+ ],
+
+ // --- Prettier integration ---
+ 'prettier/prettier': 'warn'
+ }
+ },
+
+ // Disable conflicting rules from all shareable configs
+ prettier,
+
+ // Global ignores (flat config replacement for .eslintignore)
+ globalIgnores(['**/node_modules/**', '.next/**', 'out/**', 'build/**', 'next-env.d.js'])
+]);
diff --git a/next/jsconfig.json b/next/jsconfig.json
new file mode 100644
index 000000000..17334bc45
--- /dev/null
+++ b/next/jsconfig.json
@@ -0,0 +1,43 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "paths": {
+ "*": ["./src/*"]
+ },
+ "noUnusedLocals": true,
+ "typeRoots": [
+ "../node_modules/@types",
+ "../@types",
+ "./types"
+ ],
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
+ },
+ "include": [
+ "next-env.d.js",
+ "**/*.js",
+ "**/*.jsx",
+ ".next/types/**/*.js",
+ ".next/dev/types/**/*.js",
+ "next.config.mjs"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/next/next-env.d.js b/next/next-env.d.js
new file mode 100644
index 000000000..7cc6ac764
--- /dev/null
+++ b/next/next-env.d.js
@@ -0,0 +1,6 @@
+///
+///
+import "./.next/types/routes.d.ts";
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
\ No newline at end of file
diff --git a/next/next.config.mjs b/next/next.config.mjs
new file mode 100644
index 000000000..c5d624933
--- /dev/null
+++ b/next/next.config.mjs
@@ -0,0 +1,32 @@
+const nextConfig = {
+ // todo: this need to set to true or remove it as default is true. set false as chart was giving error when first render
+ // https://github.com/apexcharts/apexcharts.js/issues/3652
+ reactStrictMode: false,
+ modularizeImports: {
+ '@mui/material': {
+ transform: '@mui/material/{{member}}'
+ },
+ '@mui/lab': {
+ transform: '@mui/lab/{{member}}'
+ },
+ '@mui/icons-material': {
+ transform: '@mui/icons-material/{{member}}'
+ }
+ },
+ images: {
+ remotePatterns: [
+ {
+ protocol: 'https',
+ hostname: 'flagcdn.com',
+ pathname: '**'
+ }
+ ],
+ localPatterns: [
+ {
+ pathname: '/assets/**'
+ }
+ ]
+ }
+};
+
+export default nextConfig;
\ No newline at end of file
diff --git a/next/package.json b/next/package.json
new file mode 100644
index 000000000..77291d4bf
--- /dev/null
+++ b/next/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "berry-free-react-material-next-js",
+ "version": "5.2.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"",
+ "lint:fix": "eslint --fix \"src/**/*.{js,jsx,ts,tsx}\"",
+ "prettier": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\""
+ },
+ "dependencies": {
+ "@emotion/cache": "11.14.0",
+ "@emotion/react": "11.14.0",
+ "@emotion/styled": "11.14.1",
+ "@mui/icons-material": "9.1.1",
+ "@mui/material": "9.1.2",
+ "@mui/utils": "9.1.1",
+ "@tabler/icons-react": "3.44.0",
+ "apexcharts": "5.15.2",
+ "framer-motion": "12.42.0",
+ "lodash-es": "4.18.1",
+ "material-ui-popup-state": "5.3.7",
+ "next": "16.0.4",
+ "react": "19.2.7",
+ "react-apexcharts": "2.1.1",
+ "react-device-detect": "2.2.3",
+ "react-dom": "19.2.7",
+ "simplebar-react": "3.3.2",
+ "swr": "2.4.2",
+ "yup": "1.7.1"
+ },
+ "devDependencies": {
+ "@eslint/js": "10.0.1",
+ "@next/eslint-plugin-next": "16.0.4",
+ "eslint": "10.7.0",
+ "eslint-config-prettier": "10.1.8",
+ "eslint-plugin-prettier": "5.5.6",
+ "eslint-plugin-react-hooks": "7.1.1",
+ "globals": "17.7.0",
+ "prettier": "3.8.5",
+ "sass": "1.101.0"
+ },
+ "packageManager": "yarn@4.17.1"
+}
diff --git a/vite/src/assets/images/auth/auth-pattern-dark.svg b/next/public/assets/images/auth/auth-pattern-dark.svg
similarity index 100%
rename from vite/src/assets/images/auth/auth-pattern-dark.svg
rename to next/public/assets/images/auth/auth-pattern-dark.svg
diff --git a/vite/src/assets/images/auth/auth-pattern.svg b/next/public/assets/images/auth/auth-pattern.svg
similarity index 100%
rename from vite/src/assets/images/auth/auth-pattern.svg
rename to next/public/assets/images/auth/auth-pattern.svg
diff --git a/vite/src/assets/images/auth/img-a2-grid-dark.svg b/next/public/assets/images/auth/img-a2-grid-dark.svg
similarity index 100%
rename from vite/src/assets/images/auth/img-a2-grid-dark.svg
rename to next/public/assets/images/auth/img-a2-grid-dark.svg
diff --git a/vite/src/assets/images/auth/img-a2-grid.svg b/next/public/assets/images/auth/img-a2-grid.svg
similarity index 100%
rename from vite/src/assets/images/auth/img-a2-grid.svg
rename to next/public/assets/images/auth/img-a2-grid.svg
diff --git a/vite/src/assets/images/icons/earning.svg b/next/public/assets/images/icons/earning.svg
similarity index 100%
rename from vite/src/assets/images/icons/earning.svg
rename to next/public/assets/images/icons/earning.svg
diff --git a/vite/src/assets/images/icons/google.svg b/next/public/assets/images/icons/google.svg
similarity index 100%
rename from vite/src/assets/images/icons/google.svg
rename to next/public/assets/images/icons/google.svg
diff --git a/vite/src/assets/images/logo-dark.svg b/next/public/assets/images/logo-dark.svg
similarity index 100%
rename from vite/src/assets/images/logo-dark.svg
rename to next/public/assets/images/logo-dark.svg
diff --git a/vite/src/assets/images/logo.svg b/next/public/assets/images/logo.svg
similarity index 100%
rename from vite/src/assets/images/logo.svg
rename to next/public/assets/images/logo.svg
diff --git a/vite/src/assets/images/users/user-round.svg b/next/public/assets/images/users/user-round.svg
similarity index 100%
rename from vite/src/assets/images/users/user-round.svg
rename to next/public/assets/images/users/user-round.svg
diff --git a/next/public/favicon.ico b/next/public/favicon.ico
new file mode 100644
index 000000000..1fc9ce781
Binary files /dev/null and b/next/public/favicon.ico differ
diff --git a/next/public/favicon.svg b/next/public/favicon.svg
new file mode 100644
index 000000000..72033ff62
--- /dev/null
+++ b/next/public/favicon.svg
@@ -0,0 +1,18 @@
+
diff --git a/next/public/file.svg b/next/public/file.svg
new file mode 100644
index 000000000..004145cdd
--- /dev/null
+++ b/next/public/file.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/next/public/globe.svg b/next/public/globe.svg
new file mode 100644
index 000000000..567f17b0d
--- /dev/null
+++ b/next/public/globe.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/next/public/next.svg b/next/public/next.svg
new file mode 100644
index 000000000..5174b28c5
--- /dev/null
+++ b/next/public/next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/next/public/vercel.svg b/next/public/vercel.svg
new file mode 100644
index 000000000..770539603
--- /dev/null
+++ b/next/public/vercel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/next/public/window.svg b/next/public/window.svg
new file mode 100644
index 000000000..b2b2a44f6
--- /dev/null
+++ b/next/public/window.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/next/src/api/menu.js b/next/src/api/menu.js
new file mode 100644
index 000000000..8089224cb
--- /dev/null
+++ b/next/src/api/menu.js
@@ -0,0 +1,41 @@
+import useSWR, { mutate } from 'swr';
+import { useMemo } from 'react';
+
+const initialState = {
+ isDashboardDrawerOpened: false
+};
+
+const endpoints = {
+ key: 'api/menu',
+ master: 'master'
+};
+
+export function useGetMenuMaster() {
+ const { data, isLoading } = useSWR(endpoints.key + endpoints.master, () => initialState, {
+ revalidateIfStale: false,
+ revalidateOnFocus: false,
+ revalidateOnReconnect: false
+ });
+
+ const memoizedValue = useMemo(
+ () => ({
+ menuMaster: data,
+ menuMasterLoading: isLoading
+ }),
+ [data, isLoading]
+ );
+
+ return memoizedValue;
+}
+
+export function handlerDrawerOpen(isDashboardDrawerOpened) {
+ // to update local state based on key
+
+ mutate(
+ endpoints.key + endpoints.master,
+ (currentMenuMaster) => {
+ return { ...currentMenuMaster, isDashboardDrawerOpened };
+ },
+ false
+ );
+}
diff --git a/next/src/app/(dashboard)/dashboard/default/page.jsx b/next/src/app/(dashboard)/dashboard/default/page.jsx
new file mode 100644
index 000000000..ed95cd9c0
--- /dev/null
+++ b/next/src/app/(dashboard)/dashboard/default/page.jsx
@@ -0,0 +1,7 @@
+import DefaultDashboard from 'views/dashboard/Default';
+
+// ==============================|| PAGE ||============================== //
+
+export default function DefaultDashboardPage() {
+ return ;
+}
diff --git a/next/src/app/(dashboard)/layout.jsx b/next/src/app/(dashboard)/layout.jsx
new file mode 100644
index 000000000..8045de26a
--- /dev/null
+++ b/next/src/app/(dashboard)/layout.jsx
@@ -0,0 +1,12 @@
+import PropTypes from 'prop-types';
+
+// project imports
+import DashboardLayout from 'layout/MainLayout';
+
+// ==============================|| DASHBOARD LAYOUT ||============================== //
+
+export default function Layout({ children }) {
+ return {children};
+}
+
+Layout.propTypes = { children: PropTypes.node };
diff --git a/next/src/app/(dashboard)/sample-page/page.jsx b/next/src/app/(dashboard)/sample-page/page.jsx
new file mode 100644
index 000000000..d55c7aa8d
--- /dev/null
+++ b/next/src/app/(dashboard)/sample-page/page.jsx
@@ -0,0 +1,7 @@
+import Sample from 'views/sample-page';
+
+// ==============================|| PAGE ||============================== //
+
+export default function SamplePage() {
+ return ;
+}
diff --git a/next/src/app/(dashboard)/utils/util-color/page.jsx b/next/src/app/(dashboard)/utils/util-color/page.jsx
new file mode 100644
index 000000000..ff101ea23
--- /dev/null
+++ b/next/src/app/(dashboard)/utils/util-color/page.jsx
@@ -0,0 +1,7 @@
+import Color from 'views/utilities/Color';
+
+// ==============================|| PAGE ||============================== //
+
+export default function ColorPage() {
+ return ;
+}
diff --git a/next/src/app/(dashboard)/utils/util-shadow/page.jsx b/next/src/app/(dashboard)/utils/util-shadow/page.jsx
new file mode 100644
index 000000000..cac722743
--- /dev/null
+++ b/next/src/app/(dashboard)/utils/util-shadow/page.jsx
@@ -0,0 +1,7 @@
+import Shadow from 'views/utilities/Shadow';
+
+// ==============================|| PAGE ||============================== //
+
+export default function ShadowPage() {
+ return ;
+}
diff --git a/next/src/app/(dashboard)/utils/util-typography/page.jsx b/next/src/app/(dashboard)/utils/util-typography/page.jsx
new file mode 100644
index 000000000..af7a09b83
--- /dev/null
+++ b/next/src/app/(dashboard)/utils/util-typography/page.jsx
@@ -0,0 +1,7 @@
+import Typography from 'views/utilities/Typography';
+
+// ==============================|| PAGE ||============================== //
+
+export default function TypographyPage() {
+ return ;
+}
diff --git a/next/src/app/(minimal)/(auth)/layout.jsx b/next/src/app/(minimal)/(auth)/layout.jsx
new file mode 100644
index 000000000..0128dcc2d
--- /dev/null
+++ b/next/src/app/(minimal)/(auth)/layout.jsx
@@ -0,0 +1,9 @@
+import PropTypes from 'prop-types';
+
+// ================================|| SIMPLE LAYOUT ||================================ //
+
+export default function Layout({ children }) {
+ return <>{children}>;
+}
+
+Layout.propTypes = { children: PropTypes.node };
diff --git a/next/src/app/(minimal)/(auth)/login/page.jsx b/next/src/app/(minimal)/(auth)/login/page.jsx
new file mode 100644
index 000000000..05a4a26d0
--- /dev/null
+++ b/next/src/app/(minimal)/(auth)/login/page.jsx
@@ -0,0 +1,7 @@
+import Login from 'views/pages/authentication/Login';
+
+// ==============================|| PAGE ||============================== //
+
+export default function LoginPage() {
+ return ;
+}
diff --git a/next/src/app/(minimal)/(auth)/register/page.jsx b/next/src/app/(minimal)/(auth)/register/page.jsx
new file mode 100644
index 000000000..78602cbc4
--- /dev/null
+++ b/next/src/app/(minimal)/(auth)/register/page.jsx
@@ -0,0 +1,7 @@
+import Register from 'views/pages/authentication/Register';
+
+// ==============================|| PAGE ||============================== //
+
+export default function RegisterPage() {
+ return ;
+}
diff --git a/next/src/app/(minimal)/layout.jsx b/next/src/app/(minimal)/layout.jsx
new file mode 100644
index 000000000..ff6acc9ac
--- /dev/null
+++ b/next/src/app/(minimal)/layout.jsx
@@ -0,0 +1,12 @@
+import PropTypes from 'prop-types';
+
+// project imports
+import MinimalLayout from 'layout/MinimalLayout';
+
+// ================================|| SIMPLE LAYOUT ||================================ //
+
+export default function Layout({ children }) {
+ return {children};
+}
+
+Layout.propTypes = { children: PropTypes.node };
diff --git a/next/src/app/layout.jsx b/next/src/app/layout.jsx
new file mode 100644
index 000000000..14fa21447
--- /dev/null
+++ b/next/src/app/layout.jsx
@@ -0,0 +1,29 @@
+import PropTypes from 'prop-types';
+
+import './../scss/style.scss';
+
+// project imports
+import ProviderWrapper from 'store/ProviderWrapper';
+
+export const metadata = {
+ title: ' Berry - React MUI Admin Dashboard Template',
+ description:
+ 'Berry is a fully customizable and powerful admin dashboard template built with React.js, MUI, and Next.js for your next project.'
+};
+
+// ==============================|| ROOT LAYOUT ||============================== //
+
+export default function RootLayout({ children }) {
+ return (
+
+
+
+
+
+ {children}
+
+
+ );
+}
+
+RootLayout.propTypes = { children: PropTypes.node };
diff --git a/next/src/app/loading.jsx b/next/src/app/loading.jsx
new file mode 100644
index 000000000..ae6311f5e
--- /dev/null
+++ b/next/src/app/loading.jsx
@@ -0,0 +1,9 @@
+'use client';
+
+import Loader from 'ui-component/Loader';
+
+// ==============================|| LOADING ||============================== //
+
+export default function Loading() {
+ return ;
+}
diff --git a/next/src/app/page.jsx b/next/src/app/page.jsx
new file mode 100644
index 000000000..7ae009746
--- /dev/null
+++ b/next/src/app/page.jsx
@@ -0,0 +1,7 @@
+import { redirect } from 'next/navigation';
+
+// ==============================|| HOME PAGE ||============================== //
+
+export default function HomePage() {
+ redirect('/dashboard/default');
+}
diff --git a/next/src/config.js b/next/src/config.js
new file mode 100644
index 000000000..6cab735ea
--- /dev/null
+++ b/next/src/config.js
@@ -0,0 +1,11 @@
+export const DASHBOARD_PATH = '/sample-page';
+export const DEFAULT_THEME_MODE = 'system';
+
+export const CSS_VAR_PREFIX = '';
+
+const config = {
+ fontFamily: `'Roboto', sans-serif`,
+ borderRadius: 8
+};
+
+export default config;
diff --git a/next/src/contexts/ConfigContext.jsx b/next/src/contexts/ConfigContext.jsx
new file mode 100644
index 000000000..cc37401b4
--- /dev/null
+++ b/next/src/contexts/ConfigContext.jsx
@@ -0,0 +1,24 @@
+'use client';
+import PropTypes from 'prop-types';
+
+import { createContext, useMemo } from 'react';
+
+// project imports
+import config from 'config';
+import { useLocalStorage } from 'hooks/useLocalStorage';
+
+// ==============================|| CONFIG CONTEXT ||============================== //
+
+export const ConfigContext = createContext(undefined);
+
+// ==============================|| CONFIG PROVIDER ||============================== //
+
+export function ConfigProvider({ children }) {
+ const { state, setState, setField, resetState } = useLocalStorage('berry-config-next-js', config);
+
+ const memoizedValue = useMemo(() => ({ state, setState, setField, resetState }), [state, setField, setState, resetState]);
+
+ return {children};
+}
+
+ConfigProvider.propTypes = { children: PropTypes.node };
diff --git a/next/src/hooks/useConfig.js b/next/src/hooks/useConfig.js
new file mode 100644
index 000000000..1b72cf0d5
--- /dev/null
+++ b/next/src/hooks/useConfig.js
@@ -0,0 +1,12 @@
+import { use } from 'react';
+import { ConfigContext } from 'contexts/ConfigContext';
+
+// ==============================|| CONFIG - HOOKS ||============================== //
+
+export default function useConfig() {
+ const context = use(ConfigContext);
+
+ if (!context) throw new Error('useSConfig must be use inside ConfigProvider');
+
+ return context;
+}
diff --git a/next/src/hooks/useLocalStorage.js b/next/src/hooks/useLocalStorage.js
new file mode 100644
index 000000000..be454fbf5
--- /dev/null
+++ b/next/src/hooks/useLocalStorage.js
@@ -0,0 +1,46 @@
+'use client';
+import { useState, useEffect, useCallback } from 'react';
+
+// ==============================|| HOOKS - LOCAL STORAGE ||============================== //
+
+export function useLocalStorage(key, defaultValue) {
+ // Load initial state from localStorage or fallback to default
+ const readValue = () => {
+ if (typeof window === 'undefined') return defaultValue;
+
+ try {
+ const item = localStorage.getItem(key);
+ return item ? JSON.parse(item) : defaultValue;
+ } catch (err) {
+ console.warn(`Error reading localStorage key “${key}”:`, err);
+ return defaultValue;
+ }
+ };
+
+ const [state, setState] = useState(readValue);
+
+ // Sync to localStorage whenever state changes
+ useEffect(() => {
+ try {
+ localStorage.setItem(key, JSON.stringify(state));
+ } catch (err) {
+ console.warn(`Error setting localStorage key “${key}”:`, err);
+ }
+ }, [key, state]);
+
+ // Update single field
+ const setField = useCallback((key, value) => {
+ setState((prev) => ({
+ ...prev,
+ [key]: value
+ }));
+ }, []);
+
+ // Reset to defaults
+ const resetState = useCallback(() => {
+ setState(defaultValue);
+ localStorage.setItem(key, JSON.stringify(defaultValue));
+ }, [defaultValue, key]);
+
+ return { state, setState, setField, resetState };
+}
diff --git a/next/src/hooks/useMenuCollapse.js b/next/src/hooks/useMenuCollapse.js
new file mode 100644
index 000000000..c22d073a6
--- /dev/null
+++ b/next/src/hooks/useMenuCollapse.js
@@ -0,0 +1,76 @@
+import { useEffect } from 'react';
+
+function matchPath(basePath, pathname) {
+ // Make sure both paths are normalized
+ const normalizedBase = basePath.replace(/\/+$/, ''); // remove trailing slash
+ const normalizedPath = pathname.replace(/\/+$/, '');
+
+ return normalizedPath === normalizedBase || normalizedPath.startsWith(normalizedBase + '/');
+}
+
+// ==============================|| MENU COLLAPSED - RECURSIVE FUNCTION ||============================== //
+
+/**
+ * Recursively traverses menu items to find and open the correct parent menu.
+ * If a menu item matches the current pathname, it marks the corresponding menu as selected and opens it.
+ *
+ * @param {NavItemType[]} items - List of menu items.
+ * @param {string} pathname - Current route pathname.
+ * @param {string | undefined} menuId - ID of the menu to be set as selected.
+ * @param {SetState} setSelected - Function to update the selected menu.
+ * @param {Dispatch>} setOpen - Function to update the open state.
+ */
+
+function setParentOpenedMenu(items, pathname, menuId, setSelected, setOpen) {
+ for (const item of items) {
+ // Base case: match the URL
+ if (item.url && matchPath(item.url, pathname)) {
+ setSelected(menuId ?? null);
+ setOpen(true);
+ return true; // child matched
+ }
+
+ // Recurse if children exist
+ if (item.children?.length) {
+ const childMatched = setParentOpenedMenu(item.children, pathname, item.id, setSelected, setOpen);
+ if (childMatched) {
+ setOpen(true);
+ setSelected(menuId ?? null);
+ return true;
+ }
+ }
+ }
+ return false; // nothing matched in this branch
+}
+
+// ==============================|| MENU COLLAPSED - HOOK ||============================== //
+
+/**
+ * Hook to handle menu collapse behavior based on the current route.
+ * Automatically expands the parent menu of the active route item.
+ *
+ * @param {NavItemType} menu - The menu object containing items.
+ * @param {string} pathname - Current route pathname.
+ * @param {boolean} miniMenuOpened - Flag indicating if the mini menu is open.
+ * @param {SetState} setSelected - Function to update selected menu state.
+ * @param {Dispatch>} setOpen - Function to update menu open state.
+ * @param {SetState} setAnchorEl - Function to update the anchor element state.
+ */
+
+export default function useMenuCollapse(menu, pathname, miniMenuOpened, setSelected, setOpen, setAnchorEl) {
+ useEffect(() => {
+ setOpen(false); // Close the menu initially
+
+ // Reset selection based on menu state
+ if (!miniMenuOpened) {
+ setSelected(null);
+ } else {
+ setAnchorEl(null);
+ }
+
+ // If menu has children, determine which should be opened
+ if (menu.children?.length) {
+ setParentOpenedMenu(menu.children, pathname, menu.id, setSelected, setOpen);
+ }
+ }, [pathname, menu.children, menu.id, miniMenuOpened, setAnchorEl, setOpen, setSelected]);
+}
diff --git a/next/src/hooks/useScriptRef.js b/next/src/hooks/useScriptRef.js
new file mode 100644
index 000000000..a60aac2f8
--- /dev/null
+++ b/next/src/hooks/useScriptRef.js
@@ -0,0 +1,13 @@
+import { useEffect, useRef } from 'react';
+
+// ==============================|| ELEMENT REFERENCE HOOKS ||============================== //
+
+export default function useScriptRef() {
+ const scripted = useRef(true);
+
+ useEffect(() => {
+ scripted.current = false;
+ }, []);
+
+ return scripted;
+}
diff --git a/next/src/layout/Customization/BorderRadius.jsx b/next/src/layout/Customization/BorderRadius.jsx
new file mode 100644
index 000000000..52682d604
--- /dev/null
+++ b/next/src/layout/Customization/BorderRadius.jsx
@@ -0,0 +1,54 @@
+'use client';
+
+// material-ui
+import Grid from '@mui/material/Grid';
+import Slider from '@mui/material/Slider';
+import Stack from '@mui/material/Stack';
+import Typography from '@mui/material/Typography';
+
+// project imports
+import useConfig from 'hooks/useConfig';
+
+// concat 'px'
+function valueText(value) {
+ return `${value}px`;
+}
+
+export default function BorderRadius() {
+ const {
+ state: { borderRadius },
+ setField
+ } = useConfig();
+
+ const handleChange = (_event, newValue) => {
+ setField('borderRadius', newValue);
+ };
+
+ return (
+
+ BORDER RADIUS
+
+
+ 4px
+
+
+ ({ '& .MuiSlider-valueLabel': { color: 'primary.lighter' } })}
+ />
+
+
+ 24px
+
+
+
+ );
+}
diff --git a/next/src/layout/Customization/FontFamily.jsx b/next/src/layout/Customization/FontFamily.jsx
new file mode 100644
index 000000000..509597270
--- /dev/null
+++ b/next/src/layout/Customization/FontFamily.jsx
@@ -0,0 +1,86 @@
+'use client';
+
+// next
+import { Inter, Poppins, Roboto } from 'next/font/google';
+
+// material-ui
+import FormControlLabel from '@mui/material/FormControlLabel';
+import Grid from '@mui/material/Grid';
+import Radio from '@mui/material/Radio';
+import RadioGroup from '@mui/material/RadioGroup';
+import Stack from '@mui/material/Stack';
+import Typography from '@mui/material/Typography';
+
+// project imports
+import useConfig from 'hooks/useConfig';
+import MainCard from 'ui-component/cards/MainCard';
+
+const inter = Inter({ subsets: ['latin'], weight: ['400', '500', '600', '700'] });
+const roboto = Roboto({ subsets: ['latin'], weight: ['300', '400', '500', '700'] });
+const poppins = Poppins({ subsets: ['latin'], weight: ['400', '500', '600', '700'] });
+
+// ==============================|| CUSTOMIZATION - FONT FAMILY ||============================== //
+
+export default function FontFamilyPage() {
+ const {
+ state: { fontFamily },
+ setField
+ } = useConfig();
+
+ const handleFontChange = (event) => {
+ setField('fontFamily', event.target.value);
+ };
+
+ const fonts = [
+ {
+ id: 'inter',
+ value: inter.style.fontFamily,
+ label: 'Inter'
+ },
+ {
+ id: 'poppins',
+ value: poppins.style.fontFamily,
+ label: 'Poppins'
+ },
+ {
+ id: 'roboto',
+ value: roboto.style.fontFamily,
+ label: 'Roboto'
+ }
+ ];
+
+ return (
+
+ FONT STYLE
+
+
+ {fonts.map((item, index) => (
+
+ ({ p: 0.75, bgcolor: fontFamily === item.value ? 'primary.lighter' : 'grey.50' })}>
+
+ }
+ label={
+
+ {item.label}
+
+ }
+ />
+
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/next/src/layout/Customization/index.jsx b/next/src/layout/Customization/index.jsx
new file mode 100644
index 000000000..34340b530
--- /dev/null
+++ b/next/src/layout/Customization/index.jsx
@@ -0,0 +1,124 @@
+'use client';
+
+import PropTypes from 'prop-types';
+import { Activity, useState } from 'react';
+
+// material-ui
+import { useColorScheme, useTheme } from '@mui/material/styles';
+import Button from '@mui/material/Button';
+import Divider from '@mui/material/Divider';
+import Drawer from '@mui/material/Drawer';
+import Fab from '@mui/material/Fab';
+import Grid from '@mui/material/Grid';
+import IconButton from '@mui/material/IconButton';
+import Stack from '@mui/material/Stack';
+import Tooltip from '@mui/material/Tooltip';
+import Typography from '@mui/material/Typography';
+import Box from '@mui/material/Box';
+
+// project imports
+import FontFamily from './FontFamily';
+import BorderRadius from './BorderRadius';
+
+import { DEFAULT_THEME_MODE } from 'config';
+import MainCard from 'ui-component/cards/MainCard';
+import AnimateButton from 'ui-component/extended/AnimateButton';
+import SimpleBar from 'ui-component/third-party/SimpleBar';
+import useConfig from 'hooks/useConfig';
+
+// assets
+import { IconSettings, IconPlus } from '@tabler/icons-react';
+
+function CustomTabPanel({ children, value, index, ...other }) {
+ return (
+
+ );
+}
+
+export default function Customization() {
+ const theme = useTheme();
+ const { resetState } = useConfig();
+ const { setMode } = useColorScheme();
+
+ // drawer on/off
+ const [open, setOpen] = useState(false);
+ const handleToggle = () => {
+ setOpen(!open);
+ };
+
+ const handleReset = () => {
+ setMode(DEFAULT_THEME_MODE);
+ resetState();
+ };
+
+ return (
+ <>
+ {/* toggle button */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Theme Customization
+
+
+
+
+
+
+
+
+
+
+ {/* font family */}
+
+
+
+
+ {/* border radius */}
+
+
+
+
+
+
+
+
+ >
+ );
+}
+
+CustomTabPanel.propTypes = { children: PropTypes.node, value: PropTypes.number, index: PropTypes.number, other: PropTypes.any };
diff --git a/next/src/layout/MainLayout/Footer.jsx b/next/src/layout/MainLayout/Footer.jsx
new file mode 100644
index 000000000..747d79c72
--- /dev/null
+++ b/next/src/layout/MainLayout/Footer.jsx
@@ -0,0 +1,61 @@
+import RouterLink from 'next/link';
+
+// material-ui
+import Link from '@mui/material/Link';
+import Stack from '@mui/material/Stack';
+import Typography from '@mui/material/Typography';
+
+export default function Footer() {
+ return (
+
+
+ © All rights reserved{' '}
+
+ CodedThemes
+
+
+
+
+ License
+
+
+ Hire us
+
+
+ Terms
+
+
+ Figma Design System
+
+
+
+ );
+}
diff --git a/next/src/layout/MainLayout/Header/NotificationSection/NotificationList.jsx b/next/src/layout/MainLayout/Header/NotificationSection/NotificationList.jsx
new file mode 100644
index 000000000..428afe8eb
--- /dev/null
+++ b/next/src/layout/MainLayout/Header/NotificationSection/NotificationList.jsx
@@ -0,0 +1,176 @@
+'use client';
+import PropTypes from 'prop-types';
+
+// material-ui
+import { useTheme } from '@mui/material/styles';
+import Avatar from '@mui/material/Avatar';
+import Button from '@mui/material/Button';
+import Card from '@mui/material/Card';
+import Chip from '@mui/material/Chip';
+import List from '@mui/material/List';
+import ListItem from '@mui/material/ListItem';
+import ListItemAvatar from '@mui/material/ListItemAvatar';
+import ListItemText from '@mui/material/ListItemText';
+import Stack from '@mui/material/Stack';
+import Typography from '@mui/material/Typography';
+import Box from '@mui/material/Box';
+
+// project imports
+import { withAlpha } from 'utils/colorUtils';
+
+// assets
+import ImageOutlinedIcon from '@mui/icons-material/ImageOutlined';
+import MarkunreadMailboxOutlinedIcon from '@mui/icons-material/MarkunreadMailboxOutlined';
+import SendOutlinedIcon from '@mui/icons-material/SendOutlined';
+import StorefrontOutlinedIcon from '@mui/icons-material/StorefrontOutlined';
+const User1 = '/assets/images/users/user-round.svg';
+
+function ListItemWrapper({ children }) {
+ const theme = useTheme();
+
+ return (
+
+ {children}
+
+ );
+}
+
+// ==============================|| NOTIFICATION LIST ITEM ||============================== //
+
+export default function NotificationList() {
+ const containerSX = { gap: 2, pl: 7 };
+
+ return (
+
+
+
+ 2 min ago
+
+ }
+ >
+
+
+
+
+
+
+ It is a long established fact that a reader will be distracted
+
+
+
+
+
+
+
+
+ 2 min ago
+
+ }
+ >
+
+
+
+
+
+ Store Verification Done} />
+
+
+ We have successfully received your request.
+
+
+
+
+
+ 2 min ago
+
+ }
+ >
+
+
+
+
+
+ Check Your Mail.} />
+
+
+ All done! Now check your inbox as you're in for a sweet treat!
+ } sx={{ width: 'min-content' }}>
+ Mail
+
+
+
+
+
+ 2 min ago
+
+ }
+ >
+
+
+
+ John Doe} />
+
+
+
+ Uploaded two file on
+
+ 21 Jan 2020
+
+
+
+
+
+ demo.jpg
+
+
+
+
+
+
+ 2 min ago
+
+ }
+ >
+
+
+
+ John Doe} />
+
+
+ It is a long established fact that a reader will be distracted
+
+
+
+
+ );
+}
+
+ListItemWrapper.propTypes = { children: PropTypes.node };
diff --git a/next/src/layout/MainLayout/Header/NotificationSection/index.jsx b/next/src/layout/MainLayout/Header/NotificationSection/index.jsx
new file mode 100644
index 000000000..d53f120bb
--- /dev/null
+++ b/next/src/layout/MainLayout/Header/NotificationSection/index.jsx
@@ -0,0 +1,172 @@
+'use client';
+
+import { Activity, useEffect, useRef, useState } from 'react';
+
+// next
+import Link from 'next/link';
+
+// material-ui
+import { useTheme } from '@mui/material/styles';
+import useMediaQuery from '@mui/material/useMediaQuery';
+import Avatar from '@mui/material/Avatar';
+import Button from '@mui/material/Button';
+import CardActions from '@mui/material/CardActions';
+import Chip from '@mui/material/Chip';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+import Divider from '@mui/material/Divider';
+import Paper from '@mui/material/Paper';
+import Popper from '@mui/material/Popper';
+import Stack from '@mui/material/Stack';
+import TextField from '@mui/material/TextField';
+import Typography from '@mui/material/Typography';
+import Box from '@mui/material/Box';
+
+// project imports
+import MainCard from 'ui-component/cards/MainCard';
+import Transitions from 'ui-component/extended/Transitions';
+import NotificationList from './NotificationList';
+
+// assets
+import { IconBell } from '@tabler/icons-react';
+
+// notification status options
+const status = [
+ {
+ value: 'all',
+ label: 'All Notification'
+ },
+ {
+ value: 'new',
+ label: 'New'
+ },
+ {
+ value: 'unread',
+ label: 'Unread'
+ },
+ {
+ value: 'other',
+ label: 'Other'
+ }
+];
+
+// ==============================|| NOTIFICATION ||============================== //
+
+export default function NotificationSection() {
+ const theme = useTheme();
+ const downMD = useMediaQuery(theme.breakpoints.down('md'));
+
+ const [open, setOpen] = useState(false);
+ const [value, setValue] = useState('');
+
+ /**
+ * anchorRef is used on different componets and specifying one type leads to other components throwing an error
+ * */
+ const anchorRef = useRef(null);
+
+ const handleToggle = () => {
+ setOpen((prevOpen) => !prevOpen);
+ };
+
+ const handleClose = (event) => {
+ if (anchorRef.current && anchorRef.current.contains(event.target)) {
+ return;
+ }
+ setOpen(false);
+ };
+
+ const prevOpen = useRef(open);
+ useEffect(() => {
+ if (prevOpen.current === true && open === false) {
+ anchorRef.current.focus();
+ }
+ prevOpen.current = open;
+ }, [open]);
+
+ const handleChange = (event) => {
+ if (event?.target.value) setValue(event?.target.value);
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+ {({ TransitionProps }) => (
+
+
+
+
+
+
+
+
+ All Notification
+
+
+
+ Mark as all read
+
+
+
+
+
+ {status.map((option) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ >
+ );
+}
diff --git a/next/src/layout/MainLayout/Header/ProfileSection/UpgradePlanCard.jsx b/next/src/layout/MainLayout/Header/ProfileSection/UpgradePlanCard.jsx
new file mode 100644
index 000000000..4ca5a688e
--- /dev/null
+++ b/next/src/layout/MainLayout/Header/ProfileSection/UpgradePlanCard.jsx
@@ -0,0 +1,72 @@
+// material-ui
+import Button from '@mui/material/Button';
+import Card from '@mui/material/Card';
+import CardContent from '@mui/material/CardContent';
+import Link from '@mui/material/Link';
+import Stack from '@mui/material/Stack';
+import Typography from '@mui/material/Typography';
+
+// project imports
+import AnimateButton from 'ui-component/extended/AnimateButton';
+
+// ==============================|| PROFILE MENU - UPGRADE PLAN CARD ||============================== //
+
+export default function UpgradePlanCard() {
+ const cardSX = {
+ content: '""',
+ position: 'absolute',
+ width: 200,
+ height: 200,
+ borderColor: 'warning.main'
+ };
+
+ return (
+
+
+
+ Upgrade your plan
+
+ 70% discount for 1 years
+ subscriptions.
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/next/src/layout/MainLayout/Header/ProfileSection/index.jsx b/next/src/layout/MainLayout/Header/ProfileSection/index.jsx
new file mode 100644
index 000000000..5f496fe00
--- /dev/null
+++ b/next/src/layout/MainLayout/Header/ProfileSection/index.jsx
@@ -0,0 +1,227 @@
+'use client';
+
+import { useEffect, useRef, useState } from 'react';
+
+// material-ui
+import Avatar from '@mui/material/Avatar';
+import Card from '@mui/material/Card';
+import CardContent from '@mui/material/CardContent';
+import Chip from '@mui/material/Chip';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+import Divider from '@mui/material/Divider';
+import InputAdornment from '@mui/material/InputAdornment';
+import List from '@mui/material/List';
+import ListItemButton from '@mui/material/ListItemButton';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import ListItemText from '@mui/material/ListItemText';
+import OutlinedInput from '@mui/material/OutlinedInput';
+import Paper from '@mui/material/Paper';
+import Popper from '@mui/material/Popper';
+import Stack from '@mui/material/Stack';
+import Switch from '@mui/material/Switch';
+import Typography from '@mui/material/Typography';
+import Box from '@mui/material/Box';
+
+// project imports
+import UpgradePlanCard from './UpgradePlanCard';
+import useConfig from 'hooks/useConfig';
+import MainCard from 'ui-component/cards/MainCard';
+import Transitions from 'ui-component/extended/Transitions';
+
+// assets
+import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined';
+import { IconLogout, IconSettings, IconUser } from '@tabler/icons-react';
+const User1 = '/assets/images/users/user-round.svg';
+
+// ==============================|| PROFILE MENU ||============================== //
+
+export default function ProfileSection() {
+ const {
+ state: { borderRadius }
+ } = useConfig();
+
+ const [sdm, setSdm] = useState(true);
+ const [value, setValue] = useState('');
+ const [notification, setNotification] = useState(false);
+ const [open, setOpen] = useState(false);
+
+ /**
+ * anchorRef is used on different components and specifying one type leads to other components throwing an error
+ * */
+ const anchorRef = useRef(null);
+
+ const handleToggle = () => {
+ setOpen((prevOpen) => !prevOpen);
+ };
+
+ const handleClose = (event) => {
+ if (anchorRef.current && anchorRef.current.contains(event.target)) {
+ return;
+ }
+
+ setOpen(false);
+ };
+
+ const prevOpen = useRef(open);
+ useEffect(() => {
+ if (prevOpen.current === true && open === false) {
+ anchorRef.current.focus();
+ }
+
+ prevOpen.current = open;
+ }, [open]);
+
+ return (
+ <>
+
+ }
+ label={}
+ ref={anchorRef}
+ aria-controls={open ? 'menu-list-grow' : undefined}
+ aria-haspopup="true"
+ onClick={handleToggle}
+ color="primary"
+ aria-label="user-account"
+ />
+
+ {({ TransitionProps }) => (
+
+
+
+ {open && (
+
+
+
+
+ Good Morning,
+
+ Johne Doe
+
+
+ Project Admin
+
+ setValue(e.target.value)}
+ placeholder="Search profile options"
+ startAdornment={
+
+
+
+ }
+ sx={{ my: 2 }}
+ aria-describedby="search-helper-text"
+ slotProps={{ input: { 'aria-label': 'profile options' } }}
+ />
+
+
+
+
+
+
+
+
+
+ Start DND Mode
+ setSdm(e.target.checked)} name="sdm" size="small" />
+
+
+ Allow Notifications
+ setNotification(e.target.checked)} name="sdm" size="small" />
+
+
+
+
+
+
+
+
+
+
+ Account Settings} />
+
+
+
+
+
+
+ Social Profile
+
+
+ }
+ />
+
+
+
+
+
+ Logout} />
+
+
+
+
+ )}
+
+
+
+ )}
+
+ >
+ );
+}
diff --git a/next/src/layout/MainLayout/Header/SearchSection/index.jsx b/next/src/layout/MainLayout/Header/SearchSection/index.jsx
new file mode 100644
index 000000000..f25c69cad
--- /dev/null
+++ b/next/src/layout/MainLayout/Header/SearchSection/index.jsx
@@ -0,0 +1,163 @@
+'use client';
+import PropTypes from 'prop-types';
+
+import { useState } from 'react';
+
+// material-ui
+import { useTheme } from '@mui/material/styles';
+import Avatar from '@mui/material/Avatar';
+import Card from '@mui/material/Card';
+import Grid from '@mui/material/Grid';
+import InputAdornment from '@mui/material/InputAdornment';
+import OutlinedInput from '@mui/material/OutlinedInput';
+import Popper from '@mui/material/Popper';
+import Box from '@mui/material/Box';
+
+// third party
+import PopupState, { bindPopper, bindToggle } from 'material-ui-popup-state';
+
+// project imports
+import Transitions from 'ui-component/extended/Transitions';
+
+// assets
+import { IconAdjustmentsHorizontal, IconSearch, IconX } from '@tabler/icons-react';
+
+function HeaderAvatar({ children, ref, ...others }) {
+ const theme = useTheme();
+
+ return (
+
+ {children}
+
+ );
+}
+
+// ==============================|| SEARCH INPUT - MOBILE||============================== //
+
+function MobileSearch({ value, setValue, popupState }) {
+ const theme = useTheme();
+
+ return (
+