Skip to content

Commit

Permalink
feat(frontend)/ELEC-499: implement navbar (#225)
Browse files Browse the repository at this point in the history
* 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
3 people authored Aug 10, 2023
1 parent d9b2871 commit 05de1cc
Show file tree
Hide file tree
Showing 5 changed files with 828 additions and 144 deletions.
6 changes: 6 additions & 0 deletions frontend-v2/public/uni-lectives.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions frontend-v2/src/app/layout.tsx
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>
);
}
165 changes: 165 additions & 0 deletions frontend-v2/src/components/Navbar/Navbar.tsx
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>
)

}
31 changes: 31 additions & 0 deletions frontend-v2/src/components/Tooltip/Tooltip.tsx
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>
);
}
Loading

0 comments on commit 05de1cc

Please sign in to comment.