diff --git a/.gitignore b/.gitignore
index b6b95a5..29a5d7e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@
.env.development.js
.env.test.js
.env.production.js
+appList.js
npm-debug.log*
yarn-debug.log*
diff --git a/__test__/components/Menubar.test.tsx b/__test__/components/Menubar.test.tsx
index b207021..b13d8fe 100644
--- a/__test__/components/Menubar.test.tsx
+++ b/__test__/components/Menubar.test.tsx
@@ -1,13 +1,65 @@
-import React from "react";
-import { screen } from "@testing-library/react";
+import { fireEvent, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import { Menubar } from "../../src/components/Menubar/Menubar";
import { renderWithProviders } from "../utils/Renderwithproviders";
describe("Calendar App Component Display Tests", () => {
+ const preloadedState = {
+ user: {
+ userData: {
+ sub: "test",
+ email: "test@test.com",
+ family_name: "Doe",
+ name: "John",
+ sid: "mockSid",
+ openpaasId: "667037022b752d0026472254",
+ },
+ },
+ };
test("renders the Menubar component", () => {
- renderWithProviders();
+ (window as any).appList = [
+ { name: "Twake", link: "/twake", icon: "twake.svg" },
+ { name: "Calendar", link: "/calendar", icon: "calendar.svg" },
+ ];
+ renderWithProviders(, preloadedState);
const navbarElement = screen.getByText("Twake");
expect(navbarElement).toBeInTheDocument();
});
+ it("renders the main title", () => {
+ (window as any).appList = [{ name: "test", icon: "test", link: "test" }];
+ renderWithProviders(, preloadedState);
+ expect(screen.getByText(/Twake/i)).toBeInTheDocument();
+ expect(screen.getByText(/Calendar/i)).toBeInTheDocument();
+ });
+
+ it("shows avatar with user initials", () => {
+ (window as any).appList = [{ name: "test", icon: "test", link: "test" }];
+ renderWithProviders(, preloadedState);
+ expect(screen.getByText("JD")).toBeInTheDocument();
+ });
+
+ it("shows AppsIcon when applist is not empty", () => {
+ (window as any).appList = [{ name: "test", icon: "test", link: "test" }];
+ renderWithProviders(, preloadedState);
+ expect(screen.getByTestId("AppsIcon")).toBeInTheDocument();
+ });
+
+ it("opens popover when clicking AppsIcon", () => {
+ (window as any).appList = [{ name: "test", icon: "test", link: "test" }];
+ renderWithProviders(, preloadedState);
+ const appsButton = screen.getByRole("button");
+ fireEvent.click(appsButton);
+ expect(screen.getByText("Twake")).toBeInTheDocument();
+ expect(screen.getByText("Calendar")).toBeInTheDocument();
+ });
+
+ it("renders app icons as links", () => {
+ (window as any).appList = [{ name: "test", icon: "test", link: "test" }];
+ renderWithProviders(, preloadedState);
+ const appsButton = screen.getByRole("button");
+ fireEvent.click(appsButton);
+
+ const twakeLink = screen.getByRole("link", { name: /test/i });
+ expect(twakeLink).toHaveAttribute("href", "test");
+ });
});
diff --git a/public/appList.example.js b/public/appList.example.js
new file mode 100644
index 0000000..3a7a28d
--- /dev/null
+++ b/public/appList.example.js
@@ -0,0 +1,7 @@
+var appList = [
+ {
+ name: "Twake",
+ link: "/twake",
+ icon: "https://twake-chat.com/tild3037-6365-4134-b838-383030366263__twake-chat-logo.svg",
+ },
+];
diff --git a/public/index.html b/public/index.html
index 6c49f1e..23a8b8d 100644
--- a/public/index.html
+++ b/public/index.html
@@ -32,6 +32,7 @@
/>
React App
+
diff --git a/src/components/Menubar/Menubar.css b/src/components/Menubar/Menubar.css
index 6996e9f..aafc6df 100644
--- a/src/components/Menubar/Menubar.css
+++ b/src/components/Menubar/Menubar.css
@@ -73,10 +73,22 @@
left: 887px;
}
-.menu-tools {
- width: 383.20001220703125;
- height: 49;
- top: 16px;
- left: 1511px;
- gap: 24px;
+.app-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 16px;
+ padding: 16px;
+ justify-items: center;
+ align-items: center;
+}
+
+.app-grid img {
+ width: 48px;
+ height: 48px;
+}
+
+.app-grid p {
+ margin-top: 6px;
+ font-size: 14px;
+ text-align: center;
}
diff --git a/src/components/Menubar/Menubar.tsx b/src/components/Menubar/Menubar.tsx
index b8bccef..8846723 100644
--- a/src/components/Menubar/Menubar.tsx
+++ b/src/components/Menubar/Menubar.tsx
@@ -1,17 +1,79 @@
-import React from "react";
+import React, { useState } from "react";
import logo from "../../static/images/calendar.svg";
+import AppsIcon from "@mui/icons-material/Apps";
import "./Menubar.css";
+import { useAppDispatch, useAppSelector } from "../../app/hooks";
+import { stringToColor } from "../../features/Events/EventDisplay";
+import { Avatar, IconButton, Popover } from "@mui/material";
+import { push } from "redux-first-history";
+
+export type AppIconProps = {
+ name: string;
+ link: string;
+ icon: string;
+};
+
export function Menubar() {
+ const user = useAppSelector((state) => state.user.userData);
+ const applist: AppIconProps[] = (window as any).appList;
+ const [anchorEl, setAnchorEl] = useState(null);
+ const dispatch = useAppDispatch();
+
+ if (!user) {
+ dispatch(push("/"));
+ }
+ const handleOpen = (event: React.MouseEvent) => {
+ setAnchorEl(event.currentTarget);
+ };
+
+ const handleClose = () => {
+ setAnchorEl(null);
+ };
+
+ const open = Boolean(anchorEl);
return (
-
+ <>
+
+
+
+ {applist.map((prop: AppIconProps) => (
+
+ ))}
+
+
+ >
);
}
export function MainTitle() {
@@ -25,3 +87,18 @@ export function MainTitle() {
);
}
+
+function AppIcon({ prop }: { prop: AppIconProps }) {
+ return (
+
+
+

+
{prop.name}
+
+
+ );
+}
diff --git a/src/features/Events/EventDisplay.tsx b/src/features/Events/EventDisplay.tsx
index 182aac3..777115d 100644
--- a/src/features/Events/EventDisplay.tsx
+++ b/src/features/Events/EventDisplay.tsx
@@ -314,7 +314,7 @@ function formatDate(date: Date) {
});
}
-function stringToColor(string: string) {
+export function stringToColor(string: string) {
let hash = 0;
for (let i = 0; i < string.length; i++) {
hash = string.charCodeAt(i) + ((hash << 5) - hash);