+ )
+}
diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx
new file mode 100644
index 0000000..af1b7a5
--- /dev/null
+++ b/src/app/dashboard/layout.tsx
@@ -0,0 +1,20 @@
+import type { Metadata } from "next"
+
+import { Navbar } from "@/components/navbar"
+
+type Props = {
+ children: React.ReactNode
+}
+
+export const metadata: Metadata = {
+ title: "Dashboard",
+}
+
+export default function DashboardLayout({ children }: Props) {
+ return (
+
+
+ {children}
+
+ )
+}
diff --git a/src/app/dashboard/loading.tsx b/src/app/dashboard/loading.tsx
new file mode 100644
index 0000000..4ab9306
--- /dev/null
+++ b/src/app/dashboard/loading.tsx
@@ -0,0 +1,3 @@
+export default function Loading() {
+ return
Loading...
+}
diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx
new file mode 100644
index 0000000..04dd873
--- /dev/null
+++ b/src/app/dashboard/page.tsx
@@ -0,0 +1,19 @@
+import { HydrationBoundary, QueryClient, dehydrate } from "@tanstack/react-query"
+
+import { FormBuilderApi } from "@/api/form-builder/form-builder.api"
+import { Dashboard } from "@/modules/dashboard"
+
+export default async function DashboardPage() {
+ const queryClient = new QueryClient()
+
+ await queryClient.fetchQuery({
+ queryKey: ["FormBuilderApi.getAllForms"],
+ queryFn: FormBuilderApi.getAllForms,
+ })
+
+ return (
+
+
+
+ )
+}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
new file mode 100644
index 0000000..0b30b0d
--- /dev/null
+++ b/src/app/layout.tsx
@@ -0,0 +1,22 @@
+import { Inter } from "next/font/google"
+
+import { cn } from "@/utils/classname"
+
+import "@/styles/globals.css"
+import Providers from "./providers"
+
+export const inter = Inter({ subsets: ["latin"], variable: "--font-inter" })
+
+type Props = {
+ children: React.ReactNode
+}
+
+export default function RootLayout({ children }: Props) {
+ return (
+
+
+ {children}
+
+
+ )
+}
diff --git a/src/app/providers.tsx b/src/app/providers.tsx
new file mode 100644
index 0000000..3f759af
--- /dev/null
+++ b/src/app/providers.tsx
@@ -0,0 +1,48 @@
+// In Next.js, this file would be called: app/providers.jsx
+"use client"
+
+// We can not useState or useRef in a server component, which is why we are
+// extracting this part out into it's own file with 'use client' on top
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
+
+function makeQueryClient() {
+ return new QueryClient({
+ defaultOptions: {
+ queries: {
+ // With SSR, we usually want to set some default staleTime
+ // above 0 to avoid refetching immediately on the client
+ staleTime: 60 * 1000,
+ },
+ },
+ })
+}
+
+let browserQueryClient: QueryClient | undefined = undefined
+
+function getQueryClient() {
+ if (typeof window === "undefined") {
+ // Server: always make a new query client
+ return makeQueryClient()
+ } else {
+ // Browser: make a new query client if we don't already have one
+ // This is very important so we don't re-make a new client if React
+ // suspends during the initial render. This may not be needed if we
+ // have a suspense boundary BELOW the creation of the query client
+ if (!browserQueryClient) browserQueryClient = makeQueryClient()
+ return browserQueryClient
+ }
+}
+
+type ProviderProps = {
+ children: React.ReactNode
+}
+
+export default function Providers({ children }: ProviderProps) {
+ // NOTE: Avoid useState when initializing the query client if you don't
+ // have a suspense boundary between this and the code that may
+ // suspend because React will throw away the client on the initial
+ // render if it suspends and there is no boundary
+ const queryClient = getQueryClient()
+
+ return {children}
+}
diff --git a/src/components/navbar/__tests__/navbar.test.tsx b/src/components/navbar/__tests__/navbar.test.tsx
index 3b79340..105a307 100644
--- a/src/components/navbar/__tests__/navbar.test.tsx
+++ b/src/components/navbar/__tests__/navbar.test.tsx
@@ -1,6 +1,5 @@
import "@testing-library/jest-dom"
import { render, screen } from "@testing-library/react"
-import mockRouter from "next-router-mock"
import { Navbar } from ".."
import { NAVBAR_LINKS } from "../navbar.constants"
@@ -21,14 +20,4 @@ describe("Navbar", () => {
expect(links[index]).toHaveAttribute("href", link.href)
})
})
-
- it("check if the active link is highlighted", () => {
- const firstLink = NAVBAR_LINKS[0]
- mockRouter.setCurrentUrl(firstLink.href)
-
- render()
-
- const activeLink = screen.getByTestId(firstLink.title.toLowerCase())
- expect(activeLink).toHaveAttribute("data-isactive", "true")
- })
})
diff --git a/src/components/navbar/navbar.tsx b/src/components/navbar/navbar.tsx
index af7b097..0e416ca 100644
--- a/src/components/navbar/navbar.tsx
+++ b/src/components/navbar/navbar.tsx
@@ -1,5 +1,7 @@
+"use client"
+
import Link from "next/link"
-import { useRouter } from "next/router"
+import { usePathname } from "next/navigation"
import { cn } from "@/utils/classname"
@@ -29,17 +31,21 @@ const NavbarLink = ({ href, title, isActive }: NavbarLinkProps) => {
}
export const Navbar = () => {
- const { pathname } = useRouter()
+ const pathname = usePathname()
const appName = process.env.NEXT_PUBLIC_APP_NAME
return (
-