Private Page — Ship Fast ⚡️
Here's what your code would look like on your privates pages (user dashboard, account, etc.).
/pages/dashboard.js
import { useState } from "react";
import { Roboto_Slab } from "next/font/google";
import { signOut } from "next-auth/react";
import apiClient from "@/libs/api";
import { usePrivate } from "@/hooks/usePrivate";
import TagSEO from "@/components/TagSEO";
const font = Roboto_Slab({ subsets: ["latin"] });
export default function Dashboard() {
// Custom hook to make private pages easier to deal with (see /hooks folder)
const [session, status] = usePrivate({
callbackUrl: "/tutorial/demo/dashboard",
});
const [isLoading, setIsLoading] = useState(false);
// A very simple example of calling an API route with authentication.
const callAPI = async () => {
setIsLoading(true);
try {
const res = await apiClient.patch("/edit-name", { name: "Marc" });
console.log(res);
} catch (e) {
console.error(e);
}
setIsLoading(false);
};
// Show a loader when the session is loading. Not needed but recommended if you show user data like email/name
if (status === "loading") {
return <p>Loading...</p>;
}
return (
<>
{/* 👇 Add all your SEO tags for the page. canonicalSlug required, other tags a prefilled with your default */}
<TagSEO title="Dashboard | FoodAI" canonicalSlug="/dashboard" />
<main
className="min-h-screen p-8 pb-24"
// 👇 The DaisyUI themes to apply (light & dark are enabled by default, you need to add 'retro' in config.taildwind.js)
data-theme="retro"
// 👇 Use next/font package to add a custom font
style={{
fontFamily: font.style.fontFamily,
}}
>
<section className="max-w-xl mx-auto space-y-8">
<h1 className="text-3xl md:text-4xl font-extrabold">
Your Food Recipes
</h1>
<p className="text-lg leading-relaxed text-base-content/80">
{status === "authenticated"
? `Welcome ${session?.user?.name}`
: "You are not logged in"}
<br />
{session?.user?.email
? `Your email is ${session?.user?.email}`
: ""}
</p>
<div>
<button className="btn btn-primary" onClick={() => callAPI()}>
{isLoading && (
<span className="loading loading-spinner loading-sm"></span>
)}
Add recipe
</button>
</div>
<div>
<button
className="btn btn-ghost"
onClick={() => signOut({ callbackUrl: "/" })}
>
Logout
</button>
</div>
</section>
</main>
</>
);
}