Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/modules/app/components/Banner/Banner.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
font-size: 5vw;
font-weight: 900;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
text-align: center;
}

.undertitle {
Expand Down
9 changes: 6 additions & 3 deletions src/modules/app/components/Banner/Banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import { useQuery } from "@tanstack/react-query";
import styles from "./Banner.module.scss";

export function Banner() {
// fetch randomfunny api using react query

const { data: randomFunny, isLoading } = useQuery({
queryKey: ["randomFunny"],
queryFn: async () => {
Expand All @@ -32,7 +30,12 @@ export function Banner() {
{isLoading ? (
<Loader type="dots" />
) : (
<Tooltip label={`Submitted by: ${randomFunny?.author}`} position="bottom" withArrow>
<Tooltip
events={{ hover: true, focus: false, touch: true }}
label={`Submitted by: ${randomFunny?.author}`}
position="bottom"
withArrow
>
<Text className={styles.undertitle}>
&quot;{randomFunny?.text.replaceAll('"', "")}&quot;
</Text>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

import { Button, Flex, Overlay, Title } from "@mantine/core";
import { IconBrandDiscord } from "@tabler/icons-react";
import { Logo } from "~/modules/layout";
import { signIn } from "next-auth/react";

export function DiscordLoginOverlay() {
// zIndex 100 is navbar, 99 ensures you can interact with navbar still
return (
<Overlay center blur={4} zIndex={99}>
<Flex direction={"column"} gap={"xl"}>
<Logo goHomeOnClick={false} />
<Title>This website requires you to be logged in.</Title>
<Flex direction={"column"} gap={"xl"} maw={"85%"}>
<Title order={2} ta={"center"}>
This website requires you to be logged in.
</Title>
<Button leftSection={<IconBrandDiscord />} size="xl" onClick={() => signIn("discord")}>
Login via Discord
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"use client";

import React, { type JSX } from "react";
import AdminLink from "next/link";
import type AdminLink from "next/link";
import Link from "next/link";
import { ActionIcon, Menu } from "@mantine/core";
import { IconLayoutDashboard, IconSpiral, IconUsersGroup } from "@tabler/icons-react";
import { Routes } from "~/constants/routes";
Expand All @@ -15,23 +16,23 @@ interface AdminLink {
href: string;
}

export const adminLinks = (iconSize = 24): AdminLink[] => [
{
icon: <IconLayoutDashboard size={iconSize} />,
label: "Dashboard",
href: Routes.ADMIN_DASHBOARD,
},
{
icon: <IconUsersGroup size={iconSize} />,
label: "Users",
href: Routes.ADMIN_USERS,
},
];

/**
* Renders admin links for sidebar
*/
export function AdminLinks() {
const adminLinks: AdminLink[] = [
{
icon: <IconLayoutDashboard />,
label: "Dashboard",
href: Routes.ADMIN_DASHBOARD,
},
{
icon: <IconUsersGroup />,
label: "Users",
href: Routes.ADMIN_USERS,
},
];

return (
<>
<Authorized role={"Admin"}>
Expand All @@ -43,14 +44,14 @@ export function AdminLinks() {
</Menu.Target>
<Menu.Dropdown>
<Menu.Label>Admin Menu</Menu.Label>
{adminLinks.map((link, index) => (
{adminLinks().map((link, index) => (
<Menu.Item
key={index}
className={style.link}
href={link.href}
leftSection={link.icon}
variant={"subtle"}
component={AdminLink}
component={Link}
>
{link.label}
</Menu.Item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,35 @@ interface Link {
href: string;
}

// Links that probably every user should see, e.g. dashboard
export const links = (iconSize = 24): Link[] => [
{
icon: <IconHome size={iconSize} />,
label: "Home",
href: Routes.HOME,
},
{
icon: <IconLink size={iconSize} />,
label: "Link",
href: Routes.LINKING,
},
{
icon: <IconJoker size={iconSize} />,
label: "Funnies",
href: Routes.FUNNY,
},
];

/**
* Renders links for sidebar
*/
export function Links() {
const pathname = usePathname();

// Links that probably every user should see, e.g. dashboard
const links: Link[] = [
{
icon: <IconHome />,
label: "Home",
href: Routes.HOME,
},
{
icon: <IconLink />,
label: "Link",
href: Routes.LINKING,
},
{
icon: <IconJoker />,
label: "Funnies",
href: Routes.FUNNY,
},
];

return (
<>
<Flex direction={"row"} gap={"xs"}>
{links.map((link, index) => (
{links().map((link, index) => (
<Flex key={index} gap={"xs"}>
<NavLink
className={style.link}
Expand Down
68 changes: 68 additions & 0 deletions src/modules/layout/components/Navbar/MobileMenu/MobileMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"use client";

import { useState } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { ActionIcon, Menu } from "@mantine/core";
import { IconMenu2, IconX } from "@tabler/icons-react";
import { Authorized } from "~/modules/users";
import { useSession } from "next-auth/react";

import { CurrentUser } from "../../../../users/components/CurrentUser/CurrentUser";
import { adminLinks } from "../AdminLinks";
import { links } from "../Links";

export function isNavActive(href: string, path: string) {
return href === "/" ? path === "/" : path?.includes(href);
}

export function MobileMenu() {
const [opened, setOpened] = useState(false);
const pathname = usePathname();
const { data: session } = useSession({ required: false });

return (
<Menu withinPortal={false} opened={opened} onChange={setOpened}>
<Menu.Target>
<ActionIcon variant="transparent" size={"xl"}>

Copilot AI Jun 27, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding an aria-label to the mobile menu toggle ActionIcon to enhance accessibility and clarify its purpose for assistive technologies.

Suggested change
<ActionIcon variant="transparent" size={"xl"}>
<ActionIcon
variant="transparent"
size={"xl"}
aria-label={opened ? "Close menu" : "Open menu"}
>

Copilot uses AI. Check for mistakes.
{opened ? <IconX size={"xl"} /> : <IconMenu2 size={"xl"} />}
</ActionIcon>
</Menu.Target>

<Menu.Dropdown>
{links(16).map((link, index) => (
<Menu.Item
bg={isNavActive(link.href, pathname) ? "primary" : "inherit"}
key={index}
leftSection={link.icon}
href={link.href}
component={Link}
>
{link.label}
</Menu.Item>
))}
<Authorized role={"Admin"}>
<Menu.Divider />
<Menu.Label>Admin Menu</Menu.Label>
{adminLinks(16).map((link, index) => (
<Menu.Item
bg={isNavActive(link.href, pathname) ? "primary" : "inherit"}
key={index}
leftSection={link.icon}
href={link.href}
component={Link}
>
{link.label}
</Menu.Item>
))}
</Authorized>
{session && (
<>
<Menu.Divider />
<CurrentUser />
</>
)}
</Menu.Dropdown>
</Menu>
);
}
1 change: 1 addition & 0 deletions src/modules/layout/components/Navbar/MobileMenu/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./MobileMenu";
48 changes: 48 additions & 0 deletions src/modules/layout/components/Navbar/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"use client";

import { Flex } from "@mantine/core";
import { useIsMobile } from "~/modules/system";
import { CurrentUser } from "~/modules/users";

import { AdminLinks } from "./AdminLinks/AdminLinks";
import { Links } from "./Links";
import { Logo } from "./Logo";
import { MobileMenu } from "./MobileMenu";
import classes from "./Navbar.module.scss";

export function Navbar() {
const isMobile = useIsMobile();

return (
<Flex
direction="row"
w="100%"
maw={"100%"}
h={"5rem"}
gap={"sm"}
align={"center"}
justify={"space-between"}
className={classes.sidebar}
px={"sm"}
>
{!isMobile ? (
<>
<Flex align={"center"} gap={"sm"}>
<Logo />
<Links />
</Flex>

<Flex align={"center"} gap={"sm"}>
<AdminLinks />
<CurrentUser />
</Flex>
</>
) : (
<Flex justify={"space-between"} align={"center"} w={"100%"}>
<Logo />
<MobileMenu />
</Flex>
)}
</Flex>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./AdminLinks";
export * from "./Links";
export * from "./Logo";
export * from "./Navbar";
export * from "./MobileMenu";
34 changes: 0 additions & 34 deletions src/modules/layout/components/Sidebar/Navbar.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/modules/layout/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from "./Layout";
export * from "./Sidebar";
export * from "./Navbar";
1 change: 1 addition & 0 deletions src/modules/system/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./useConfirmModal";
export * from "./useRoleColor";
export * from "./useIsMobile";
6 changes: 6 additions & 0 deletions src/modules/system/hooks/useIsMobile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { em } from "@mantine/core";
import { useMediaQuery } from "@mantine/hooks";

export function useIsMobile(): boolean {
return useMediaQuery(`(max-width: ${em(750)})`);
}
Loading