-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(frontend)/ELEC-499: implement navbar (#225)
* add initial oauth support * Moved navbar to layout * Added links to icons * feature/ELEC-499: added responsiveness * feature/ELEC-499: interactive logout button * feature/ELEC-499: collapsed navbar * feature/ELEC-499: re-factored into collapsed and non-collapsed views * feature/ELEC-499: tooltips * feature/ELEC-499: xs responsiveness * feature/ELEC-499: changed link to a * feature/ELEC-499: fixed linting * add federated authentication support * add federated authentication support * feature/ELEC-499: restored package-lock.json * add comment for module augmentation * create middleware * feature/ELEC-499: re-structure logic * add initial oauth support * remove auth server remove login window remove validation on course page * remove auth server modify docker * feature/ELEC-499: transition * feature/ELEC-499: dark background + auth * remove dull background * fix user typing --------- Co-authored-by: Ahnaf Tazwar <[email protected]> Co-authored-by: joanna209 <[email protected]>
- Loading branch information
1 parent
d9b2871
commit 05de1cc
Showing
5 changed files
with
828 additions
and
144 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,26 @@ | ||
import "./globals.css"; | ||
import Navbar from "@/components/Navbar/Navbar"; | ||
import { getServerSession } from "next-auth"; | ||
import { authOptions } from "@/lib/auth"; | ||
|
||
export const metadata = { | ||
title: "uni-lectives", | ||
description: "Course review website for UNSW made by CSESoc", | ||
}; | ||
|
||
export default function RootLayout({ | ||
export default async function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
const session = await getServerSession(authOptions); | ||
console.log("layout re-rendered") | ||
return ( | ||
<html lang="en" className="font-custom"> | ||
<body>{children}</body> | ||
<body> | ||
<Navbar zid={session?.user?.id}/> | ||
<div className="ml-20 xs:ml-15">{children}</div> | ||
</body> | ||
</html> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
"use client"; | ||
|
||
import { useState, useRef, useEffect } from "react"; | ||
import Image from "next/image"; | ||
import logo from "../../../public/uni-lectives.svg"; | ||
import { BookOpenIcon, PencilSquareIcon, ShieldCheckIcon, UserCircleIcon, BarsArrowDownIcon, BarsArrowUpIcon, MoonIcon, ArrowRightOnRectangleIcon, ArrowLeftOnRectangleIcon } from "@heroicons/react/24/outline"; | ||
import Tooltip from "@/components/Tooltip/Tooltip"; | ||
|
||
type NavbarProps = { | ||
zid: string | undefined; | ||
} | ||
|
||
export default function Navbar({ | ||
zid | ||
}: NavbarProps ) { | ||
const [logout, setLogout] = useState(false); | ||
const [collapsed, setCollapsed] = useState(true); | ||
|
||
const ref = useRef<HTMLDivElement>(null); | ||
|
||
useEffect(() => { | ||
function handleClickOutside(event: any) { | ||
if (ref.current && !ref.current.contains(event.target)) { | ||
setCollapsed(true); | ||
} | ||
} | ||
// Bind the event listener | ||
document.addEventListener("mousedown", handleClickOutside); | ||
return () => { | ||
// Unbind the event listener on clean up | ||
document.removeEventListener("mousedown", handleClickOutside); | ||
}; | ||
}, [ref]); | ||
|
||
function handleLogout(e: React.MouseEvent<Element, MouseEvent>) { | ||
setLogout(true); | ||
if (!logout) { | ||
e.preventDefault(); | ||
} | ||
} | ||
|
||
function handleCollapse(val: boolean) { | ||
setCollapsed(val); | ||
} | ||
|
||
return ( | ||
// Enlarged (non-collapsed) View | ||
<div ref={ref} className={collapsed ? "fixed flex flex-col items-center w-20 h-screen gap-4 p-4 duration-150 bg-gray-50 z-50 xs:p-2 xs:w-15 xs:gap-2" : "fixed flex flex-col w-72 h-screen gap-4 p-4 bg-gray-50 z-40 duration-150"}> | ||
{/* Logo */} | ||
<div className="flex flex-row items-center justify-between h-10 p-2"> | ||
<Tooltip tooltip={collapsed ? "" : ""}> | ||
<a href="/"> | ||
<Image | ||
src={logo} | ||
width={33} | ||
height={33} | ||
alt="logo" | ||
priority | ||
/> | ||
</a> | ||
</Tooltip> | ||
<p className={collapsed ? "hidden" : "text-xl font-semibold whitespace-nowrap "}>uni-lectives</p> | ||
<BarsArrowDownIcon onClick={() => handleCollapse(true)} className={collapsed ? "hidden" : "w-12 h-12 p-3 rotate-90 hover:bg-slate-200 rounded-xl"} /> | ||
</div> | ||
{/* Navbar Container */} | ||
<div className="flex flex-col h-full w-full justify-between border-t-2 border-gray-200"> | ||
{/* Review Options */} | ||
<div className={`flex flex-col gap-3 py-3 ${collapsed ? "items-center" : "items-left"}`}> | ||
<a className={collapsed ? "flex" : "flex flex-row items-center hover:bg-slate-200 rounded-xl"} href="/"> | ||
<Tooltip tooltip={collapsed ? "Browse Courses" : ""}> | ||
<BookOpenIcon className="w-12 h-12 p-3 hover:bg-slate-200 rounded-xl" /> | ||
</Tooltip> | ||
<span className={collapsed ? "hidden" : "whitespace-nowrap"}>Browse Courses</span> | ||
</a> | ||
<a className={collapsed ? "flex" : "flex flex-row items-center hover:bg-slate-200 rounded-xl"} href="/user/zid"> | ||
<Tooltip tooltip={collapsed ? "My Reviews" : ""}> | ||
<PencilSquareIcon className="w-12 h-12 p-3 hover:bg-slate-200 rounded-xl" /> | ||
</Tooltip> | ||
<span className={collapsed ? "hidden" : "whitespace-nowrap"}>My Reviews</span> | ||
</a> | ||
<a className={collapsed ? "flex" : "flex flex-row items-center hover:bg-slate-200 rounded-xl"} href="/terms-and-conditions"> | ||
<Tooltip tooltip={collapsed ? "Terms and Conditions" : ""}> | ||
<ShieldCheckIcon className="w-12 h-12 p-3 hover:bg-slate-200 rounded-xl" /> | ||
</Tooltip> | ||
<span className={collapsed ? "hidden" : "whitespace-nowrap"}>Terms and Conditions</span> | ||
</a> | ||
</div> | ||
{/* Account Options */} | ||
<div className={`flex flex-col gap-4 py-2 ${collapsed ? "items-center" : "items-left"}`}> | ||
<div className={collapsed ? "flex flex-col gap-3" : "flex flex-row justify-between gap-2"}> | ||
<Tooltip tooltip={"Expand"}> | ||
<BarsArrowUpIcon onClick={(e) => setCollapsed(false)} className={collapsed ? "w-12 h-12 p-3 rotate-90 hover:bg-slate-200 rounded-xl" : "hidden"} /> | ||
</Tooltip> | ||
{collapsed ? ( | ||
<Tooltip tooltip={zid ? `${zid}` : "My Account"}> | ||
<a href="user/zid"> | ||
<UserCircleIcon className="w-12 h-12 p-3 hover:bg-slate-200 rounded-xl" /> | ||
</a> | ||
</Tooltip> | ||
) : ( | ||
<a className="flex flex-row w-full items-center hover:bg-slate-200 rounded-xl" href={zid ? `user/${zid}` : "api/auth/signin"}> | ||
<UserCircleIcon className="w-12 h-12 p-3" /> | ||
<span className="whitespace-nowrap">{zid ? zid : "My Account"}</span> | ||
</a> | ||
)} | ||
{collapsed ? ( | ||
<Tooltip tooltip={"Dark Mode"}> | ||
<MoonIcon title="Dark Mode" className="w-12 h-12 p-3 hover:bg-slate-200 rounded-xl" /> | ||
</Tooltip> | ||
) : ( | ||
<MoonIcon title="Dark Mode" className="w-12 h-12 p-3 hover:bg-slate-200 rounded-xl" /> | ||
)} | ||
</div> | ||
{zid ? ( | ||
collapsed ? ( | ||
<Tooltip tooltip={logout ? "Are you sure?" : "Logout"}> | ||
<a | ||
href={logout ? "/api/auth/signout" : "#"} | ||
onClick={(e) => { setLogout(true); if (!logout) { e.preventDefault() } }} | ||
onMouseLeave={() => setLogout(false)} | ||
className={`flex flex-row items-center justify-center rounded-xl gap-2 ${logout ? "hover:text-red-600 hover:bg-red-100" : "hover:bg-slate-200"}`}> | ||
<ArrowRightOnRectangleIcon className="w-12 h-12 p-3" /> | ||
</a> | ||
</Tooltip> | ||
) : ( | ||
<a | ||
href={logout ? "/api/auth/signout" : "#"} | ||
onClick={(e) => handleLogout(e)} | ||
onMouseLeave={() => setLogout(false)} | ||
className={`flex flex-row items-center justify-center rounded-xl gap-2 ${logout ? "hover:text-red-600 hover:bg-red-100" : "hover:bg-slate-200"}`}> | ||
<ArrowRightOnRectangleIcon className="w-6 h-12 py-3" /> | ||
{!logout ? ( | ||
<span className="whitespace-nowrap">Logout</span> | ||
) : ( | ||
<span>Are you sure?</span> | ||
)} | ||
</a> | ||
)) : ( | ||
collapsed ? ( | ||
<Tooltip tooltip={"Login"}> | ||
<a | ||
href={"/api/auth/signin"} | ||
className="flex flex-row items-center justify-center rounded-xl gap-2 hover:bg-slate-200"> | ||
<ArrowLeftOnRectangleIcon className="w-12 h-12 rotate-180 p-3" /> | ||
</a> | ||
</Tooltip> | ||
) : ( | ||
<a | ||
href={"/api/auth/signin"} | ||
className="flex flex-row items-center justify-center rounded-xl gap-2 hover:bg-slate-200"> | ||
<ArrowLeftOnRectangleIcon className="w-6 h-12 rotate-180 py-3" /> | ||
<span>Login</span> | ||
</a> | ||
))} | ||
|
||
<div className="flex flex-col gap-3 max-h-20"> | ||
<span className={collapsed ? "hidden" : "text-xs"}>By using this site, you agree to the <a href="/terms-and-conditions" className="inline text-blue-500 hover:underline">terms and conditions</a>.</span> | ||
<span className={collapsed ? "hidden" : "text-xs"}>© CSESoc 2023, v1.0.0</span> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { ReactNode } from "react"; | ||
|
||
type TooltipProps = { | ||
children: ReactNode; | ||
tooltip?: string; | ||
}; | ||
|
||
export default function Tooltip({ children, tooltip }: TooltipProps) { | ||
return ( | ||
<div className="group relative inline-block"> | ||
{children} | ||
{tooltip && ( | ||
<div className=" | ||
scale-0 group-hover:scale-100 | ||
absolute left-full top-1/2 transform -translate-y-1/2 ml-1 | ||
whitespace-nowrap" | ||
> | ||
<div className="relative"> | ||
<div className=" | ||
absolute right-full top-1/2 transform -translate-y-1/2 | ||
w-0 h-0 border-t-4 border-t-transparent border-r-8 border-b-4 border-b-transparent border-r-white" | ||
/> | ||
<span className="py-2 px-4 text-sm text-black whitespace-nowrap rounded-md bg-white shadow-lg"> | ||
{tooltip} | ||
</span> | ||
</div> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
} |
Oops, something went wrong.