Skip to content

Commit

Permalink
Create the departmental account icon
Browse files Browse the repository at this point in the history
  • Loading branch information
Michelle Ho committed Nov 23, 2024
1 parent c88af0e commit f7a55fa
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 20 deletions.
1 change: 1 addition & 0 deletions ui/public/id-card-solid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions ui/public/key-solid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions ui/public/user-solid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions ui/public/wrench-solid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 61 additions & 0 deletions ui/src/components/layout/navbar/dept-account-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use client';

import { useState } from 'react';

import { School } from 'lucide-react';
import DynamicModal from '@/components/modal/dynamic-modal';
import { faUser } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import User from '@/lib/access/user';

const DeptAccountIcon = ({ currentUser }: { currentUser: User }) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const openDepartmentalModal = () => {
setIsModalOpen(true);
};

const closeDepartmentalModal = () => {
setIsModalOpen(false);
};

return (
<>
{currentUser.uid == currentUser.uhUuid && (
<div
onClick={openDepartmentalModal}
className="flex justify-center items-center rounded-full
h-[45px] w-[45px] bg-seafoam mx-auto relative lg:ml-24"
>
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<FontAwesomeIcon aria-label="user" icon={faUser} width={14} height={16} />
<div
className="bg-blue-background rounded-full flex justify-center
items-center h-[20px] w-[25px] absolute left-7 bottom-0"
>
<School className="fill-white stroke-1 p-0.5" aria-label="school" />
</div>
</TooltipTrigger>
<TooltipContent>
<p>You are not in your personal account</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
)}
{isModalOpen && (
<DynamicModal
open={isModalOpen}
title={'Warning'}
body={'You are not in your personal account.'}
buttons={[]}
onClose={closeDepartmentalModal}
/>
)}
</>
);
};

export default DeptAccountIcon;
2 changes: 1 addition & 1 deletion ui/src/components/layout/navbar/navbar-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet';
import { User } from 'next-cas-client';
import User from '@/lib/access/user.ts';
import Link from 'next/link';
import { NavbarLinks } from './navbar-links';
import { useState } from 'react';
Expand Down
5 changes: 4 additions & 1 deletion ui/src/components/layout/navbar/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import { NavbarLinks } from './navbar-links';
import LoginButton from './login-button';
import NavbarMenu from './navbar-menu';
import TimeoutModal from '@/components/modal/timeout-modal';
import { getUser } from '@/lib/access/user';
import { getUser } from '@/lib/access/user.ts';
import Role from '@/lib/access/role';
import DeptAccountIcon from '@/components/layout/navbar/dept-account-icon';

const Navbar = async () => {
const currentUser = await getUser();

return (
<>
<TimeoutModal currentUser={currentUser} />
Expand All @@ -34,6 +36,7 @@ const Navbar = async () => {
/>
</Link>
</div>
<DeptAccountIcon currentUser={currentUser} />
<div className="text-lg text-uh-black my-auto lg:space-x-5">
{NavbarLinks.filter(
(navbarLink) =>
Expand Down
21 changes: 7 additions & 14 deletions ui/src/components/modal/dynamic-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,34 @@ import {
AlertDialogFooter,
AlertDialogCancel
} from '@/components/ui/alert-dialog';
import { ReactNode, useState } from 'react';
import { ReactNode } from 'react';
import { Button } from '@/components/ui/button';

const DynamicModal = ({
open,
title,
body,
buttons
buttons,
onClose
}: {
open: boolean;
title: string;
body: string;
buttons?: ReactNode[];
onClose: () => void;
}) => {
const [openDynamicModal, setOpenDynamicModal] = useState(open);

/**
* Closes the modal.
*/
const close = () => {
setOpenDynamicModal(false);
};

return (
<AlertDialog open={openDynamicModal}>
<AlertDialog open={open}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{title}</AlertDialogTitle>
<AlertDialogDescription>{body}</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={() => close()}>OK</AlertDialogCancel>
<AlertDialogCancel onClick={onClose}>OK</AlertDialogCancel>
{/*Any buttons that should lead the user to a different page.*/}
{buttons?.map((button, index) => (
<Button key={index} onClick={() => close()}>
<Button key={index} onClick={onClose}>
{button}
</Button>
))}
Expand Down
27 changes: 23 additions & 4 deletions ui/tests/components/modal/dynamic-modal.test.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { fireEvent, render, screen } from '@testing-library/react';
import DynamicModal from '@/components/modal/dynamic-modal';
import Link from 'next/link';
import { useState } from 'react';

describe('DynamicModal', () => {
it('should open an informational modal with test contents and no extra buttons', () => {
render(<DynamicModal open={true} title="A Dynamic Title" body="Some dynamic message here." />);
const onClose = jest.fn();
render(
<DynamicModal open={true} title="A Dynamic Title" onClose={onClose} body="Some dynamic message here." />
);
fireEvent.focus(document);

expect(screen.getByRole('alertdialog', { name: 'A Dynamic Title' })).toBeInTheDocument();
Expand All @@ -14,11 +18,13 @@ describe('DynamicModal', () => {
});

it('should open an informational modal with test contents and extra buttons', () => {
const onClose = jest.fn();
render(
<DynamicModal
open={true}
title="A Dynamic Title"
body="Some dynamic message here."
onClose={onClose}
buttons={[<>Button1</>, <>Button2</>]}
/>
);
Expand All @@ -33,7 +39,16 @@ describe('DynamicModal', () => {
});

it('should close the modal upon clicking the OK button', () => {
render(<DynamicModal open={true} title="A Dynamic Title" body="Some dynamic message here." buttons={[]} />);
const onClose = jest.fn();
render(
<DynamicModal
open={true}
title="A Dynamic Title"
body="Some dynamic message here."
onClose={onClose}
buttons={[]}
/>
);
fireEvent.focus(document);

expect(screen.getByRole('alertdialog', { name: 'A Dynamic Title' })).toBeInTheDocument();
Expand All @@ -43,15 +58,18 @@ describe('DynamicModal', () => {
expect(screen.getByRole('button', { name: 'OK' })).toBeInTheDocument();

fireEvent.click(screen.getByRole('button', { name: 'OK' }));
expect(screen.queryByRole('alertdialog', { name: 'A Dynamic Title' })).not.toBeInTheDocument();
// Cannot use useState in the test environment so expect the onClose function to be called once.
expect(onClose).toHaveBeenCalledTimes(1); // Assumes the onClose function toggles a useState variable.
});

it('should close the modal and route to the provided link (Feedback)', () => {
const onClose = jest.fn();
render(
<DynamicModal
open={true}
title="A Modal to the Feedback Page"
body="Click Feedback to go to the Feedback Page."
onClose={onClose}
buttons={[
<Link key={'feedbackButton'} href={'/feedback'}>
Feedback
Expand All @@ -69,6 +87,7 @@ describe('DynamicModal', () => {
expect(screen.getByRole('link', { name: 'Feedback' })).toHaveAttribute('href', '/feedback');

fireEvent.click(screen.getByRole('button', { name: 'Feedback' }));
expect(screen.queryByRole('alertdialog', { name: 'A Modal to the Feedback Page' })).not.toBeInTheDocument();
// Cannot use useState in the test environment so expect the onClose function to be called once.
expect(onClose).toHaveBeenCalledTimes(1); // Assumes the onClose function toggles a useState variable.
});
});

0 comments on commit f7a55fa

Please sign in to comment.