Skip to content

Commit

Permalink
Merge pull request #798 from PrudentBird/prudentbird
Browse files Browse the repository at this point in the history
feat: Implement next auth session, routing config, userContext
  • Loading branch information
ThePrimeJnr authored Jul 30, 2024
2 parents 5f771a0 + f9efb14 commit 3865934
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 137 deletions.
14 changes: 12 additions & 2 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "standalone",
output: 'standalone',
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'lh3.googleusercontent.com',
port: '',
pathname: '/**',
},
],
},
};

export default nextConfig;
export default nextConfig;
28 changes: 23 additions & 5 deletions src/app/dashboard/(admin)/_components/layout/navbar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
"use client";

import { BellIcon, ChevronDown, HelpCircle, SearchIcon } from "lucide-react";
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useEffect } from "react";

import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
import UserCard from "~/components/card/user-card";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import UnreadNotificationCard from "../../unread-notification-card/UnreadNotificationCard";

interface User {
email: string;
image: string;
name: string;
}

const DashboardNavbar = () => {
const { data: session, status } = useSession();
const router = useRouter();
useEffect(() => {
if (status === "unauthenticated") {
router.push("/login");
}
}, [status, router]);

return (
<nav
className="fixed left-[50px] right-0 top-0 z-50 border-b-[0.5px] border-border md:left-[220px] lg:left-[252px]"
Expand Down Expand Up @@ -59,10 +78,9 @@ const DashboardNavbar = () => {
/>
</div>
<div className="hover:bg-black-1 flex w-full max-w-[64px] cursor-pointer items-center justify-between gap-2">
<Avatar data-testid="avatar" className="h-10 w-10">
<AvatarImage src="https://github.com/shadcn.png" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
{status === "authenticated" && (
<UserCard user={session?.user as User} />
)}
<ChevronDown
data-testid="chevronDown"
className="2-5 h-5 text-neutral-dark-1"
Expand Down

This file was deleted.

File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import {
Menu,
SearchIcon,
} from "lucide-react";
import { useSession } from "next-auth/react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { usePathname, useRouter } from "next/navigation";
import { useEffect } from "react";

import DashboardLogo from "~/app/dashboard/(admin)/_components/layout/logo";
import UnreadNotificationCard from "~/app/dashboard/(admin)/_components/unread-notification-card/UnreadNotificationCard";
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
import UserCard from "~/components/card/user-card";
import {
Popover,
PopoverContent,
Expand Down Expand Up @@ -42,9 +44,22 @@ const navlinks = [
},
];

interface User {
email: string;
image: string;
name: string;
}

const UserNavbar = () => {
const pathname = usePathname();
const currentPath = pathname?.split("/")[2];
const { data: session, status } = useSession();
const router = useRouter();
useEffect(() => {
if (status === "unauthenticated") {
router.push("/login");
}
}, [status, router]);

return (
<nav
Expand Down Expand Up @@ -113,10 +128,9 @@ const UserNavbar = () => {
/>
</div>
<div className="hover:bg-black-1 flex w-full max-w-[64px] cursor-pointer items-center justify-between gap-2">
<Avatar data-testid="avatar" className="h-10 w-10">
<AvatarImage src="https://github.com/shadcn.png" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
{status === "authenticated" && (
<UserCard user={session?.user as User} />
)}
<ChevronDown
data-testid="chevronDown"
className="2-5 h-5 text-neutral-dark-1"
Expand Down
3 changes: 2 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "./globals.css";

import Providers from "~/components/providers";
import { Toaster } from "~/components/ui/toaster";
import AuthProvider from "~/contexts/authContext";

const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
Expand All @@ -22,7 +23,7 @@ export default function RootLayout({
<body className={inter.className}>
<div className="mx-auto w-full">
<Providers />
{children}
<AuthProvider>{children}</AuthProvider>
<Toaster />
</div>
</body>
Expand Down
76 changes: 40 additions & 36 deletions src/components/card/user-card.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import { AnimatePresence, motion } from "framer-motion";
import { signOut } from "next-auth/react";
import Image from "next/image";
import { useEffect, useState } from "react";

import { useUser } from "~/hooks/user/use-user";
import { cn } from "~/lib/utils";
import { Button } from "../ui/button";
import CustomButton from "../common/common-button/common-button";

const UserCard = ({ email }: { email: string }) => {
const { updateUser } = useUser();
const [isLogout, setIsLogout] = useState(false);

const handleLogout = () => {
updateUser({ email: "", name: "" });
setIsLogout(false);
};
interface User {
email: string;
image: string;
name: string;
}

const handleEscapeClick = (event: KeyboardEvent) => {
if (event.key === "Escape") {
setIsLogout(false);
}
};
const UserCard = ({ user }: { user: User }) => {
const [isLogout, setIsLogout] = useState(false);

useEffect(() => {
const handleEscapeClick = (event: KeyboardEvent) => {
if (event.key === "Escape") {
setIsLogout(false);
}
};

document.addEventListener("keydown", handleEscapeClick);
return () => {
document.removeEventListener("keydown", handleEscapeClick);
Expand All @@ -29,23 +30,32 @@ const UserCard = ({ email }: { email: string }) => {

return (
<div className="relative w-fit">
<Button
variant={"ghost"}
size={"icon"}
onClick={() => setIsLogout(!isLogout)}
className={cn(
"grid size-9 place-items-center rounded-full bg-orange-500 text-xl font-medium text-white sm:text-2xl sm:font-bold",
)}
>
{email[0]}
</Button>
{user?.image ? (
<div
className="flex h-full w-full cursor-pointer items-center justify-center overflow-hidden rounded-full"
onClick={() => setIsLogout(!isLogout)}
>
<Image
src={user.image}
alt={`${user.name}'s profile image`}
width={64}
height={64}
/>
</div>
) : (
<CustomButton
variant="primary"
onClick={() => setIsLogout(!isLogout)}
className="flex h-full w-full items-center justify-center overflow-hidden rounded-full text-center text-xl capitalize"
>
{user?.email[0]}
</CustomButton>
)}
<AnimatePresence>
{isLogout && (
<>
<div
onClick={() => {
setIsLogout(false);
}}
onClick={() => setIsLogout(false)}
className={cn(
"fixed left-0 top-0 z-[99] min-h-screen w-full overflow-hidden bg-neutral-700/0 transition-all duration-300 lg:hidden",
isLogout
Expand All @@ -60,15 +70,9 @@ const UserCard = ({ email }: { email: string }) => {
transition={{ type: "spring", stiffness: 300, damping: 30 }}
className="absolute -bottom-16 -right-2 z-[999] flex w-[150px] flex-col gap-y-2 rounded-xl bg-white p-2 shadow-lg"
>
<Button
variant={"ghost"}
onClick={handleLogout}
className={cn(
"w-full text-xl font-medium text-orange-500 sm:font-bold",
)}
>
<CustomButton variant="primary" onClick={() => signOut()}>
Logout
</Button>
</CustomButton>
</motion.div>
</>
)}
Expand Down
18 changes: 13 additions & 5 deletions src/components/layouts/navbar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
"use client";

import { useSession } from "next-auth/react";
import Link from "next/link";
import { useEffect, useState } from "react";

import UserCard from "~/components/card/user-card";
import Logo from "~/components/common/logo";
import { useUser } from "~/hooks/user/use-user";
import { cn } from "~/lib/utils";
import { NAV_LINKS } from "./links";
import MobileNav from "./mobile-navbar";

interface User {
email: string;
image: string;
name: string;
}

const Navbar = () => {
const [scrolling, setIsScrolling] = useState<boolean>(false);
const { user } = useUser();
const { data: session, status } = useSession();

const handleScrollEvent = () => {
if (window.scrollY > 1) {
Expand All @@ -36,7 +42,7 @@ const Navbar = () => {
className={cn(
`relative mx-auto flex w-full max-w-[1200px] items-center gap-x-4 transition-all duration-500 md:justify-between`,
scrolling ? "py-2" : "py-4 md:py-9",
user.email && "justify-between",
status === "authenticated" && "justify-between md:justify-between",
)}
>
<MobileNav />
Expand All @@ -55,7 +61,7 @@ const Navbar = () => {
);
})}
</div>
{!user.email && (
{status !== "authenticated" && (
<div className="w-fullx hidden items-center justify-end gap-x-4 justify-self-end md:flex lg:gap-x-8">
<Link
href="/login"
Expand All @@ -71,7 +77,9 @@ const Navbar = () => {
</Link>
</div>
)}
{user.email && <UserCard email={user.email} />}
{status === "authenticated" && (
<UserCard user={session?.user as User} />
)}
</div>
</nav>
);
Expand Down
11 changes: 11 additions & 0 deletions src/components/layouts/navbar/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use client";

import AuthProvider from "~/contexts/authContext";

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return <AuthProvider>{children}</AuthProvider>;
}
Loading

0 comments on commit 3865934

Please sign in to comment.