Skip to content

Commit

Permalink
Merge pull request #104 from uwblueprint/ryan-jesse/announcement-home…
Browse files Browse the repository at this point in the history
…page-component

announcement homepage component
  • Loading branch information
jeessh authored Sep 21, 2024
2 parents 26c9275 + b89149f commit c8081ed
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 45 deletions.
11 changes: 10 additions & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import PrivateRoute from "./components/auth/PrivateRoute";
import LoginPage from "./components/auth/LoginPage";
import SignupPage from "./components/auth/SignupPage";
import ResetPasswordPage from "./components/auth/ResetPasswordPage";
import HomePage from "./components/pages/home/HomePage";
import AnnouncementsPage from "./components/pages/announcements/AnnouncementsPage";

Check warning on line 32 in frontend/src/App.tsx

View workflow job for this annotation

GitHub Actions / run-lint

'AnnouncementsPage' is defined but never used
import TasksPage from "./components/pages/tasks/TasksPage";
import SchedulePage from "./components/pages/schedule/SchedulePage";
Expand Down Expand Up @@ -83,7 +84,15 @@ const App = (): React.ReactElement => {
path={Routes.HOME_PAGE}
element={
<PrivateRoute>
<AnnouncementsPage />
<HomePage />
</PrivateRoute>
}
/>
<Route
path={Routes.ANNOUNCEMENTS_PAGE}
element={
<PrivateRoute>
<HomePage />
</PrivateRoute>
}
/>
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/common/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ const SideBar: React.FC = () => {
};

const pages = [
{ label: "Home", route: Routes.HOME_PAGE }, // NEED NEW HOME PAGE
{ label: "Home", route: Routes.HOME_PAGE },
{ label: "Tasks", route: Routes.TASKS_PAGE },
{ label: "Approvals", route: Routes.APPROVALS_PAGE },
{ label: "Schedule", route: Routes.SCHEDULE_PAGE },
{ label: "Announcements", route: Routes.HOME_PAGE }, // NEED NEW NAME
{ label: "Participants", route: Routes.RESIDENTS_PAGE }, // RESIDENTS/PARTICIPANTS
Expand Down
97 changes: 54 additions & 43 deletions frontend/src/components/pages/announcements/AnnouncementsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,54 @@
import React, { useEffect, useState } from "react";
import { Flex } from "@chakra-ui/react";

import { GroupAnnouncements } from "../../../types/NotificationTypes";
import AnnouncementsGroups from "./AnnouncementsGroups";
import AnnouncementsView from "./AnnouncementsView";
import { announcementsMockData } from "../../../mocks/notifications";

const AnnouncementsPage = (): React.ReactElement => {
const [announcements, setAnnouncements] = useState<GroupAnnouncements>({});
const [selectedGroup, setSelectedGroup] = useState<string>("");
const [addingNewRoom, setAddingNewRoom] = useState<boolean>(false);
const [selectedRooms, setSelectedRooms] = useState<number[]>([]);

useEffect(() => {
// TODO: Fetch announcements from API
setAnnouncements(announcementsMockData);
}, []);

return (
<Flex flexDir="column" flexGrow={1}>
<Flex flexDir="row" alignItems="flex-start" w="100%" flexGrow={1}>
<AnnouncementsGroups
announcements={announcements}
setSelectedGroup={setSelectedGroup}
addingNewRoom={addingNewRoom}
setAddingNewRoom={setAddingNewRoom}
selectedRooms={selectedRooms}
/>
<AnnouncementsView
announcements={announcements}
selectedGroup={selectedGroup}
addingNewRoom={addingNewRoom}
setAddingNewRoom={setAddingNewRoom}
selectedRooms={selectedRooms}
setSelectedRooms={setSelectedRooms}
/>
</Flex>
</Flex>
);
};

export default AnnouncementsPage;
import React, { useEffect, useState } from "react";
import { Flex } from "@chakra-ui/react";

import {
GroupAnnouncements,
Announcement,
} from "../../../types/NotificationTypes";
import AnnouncementsGroups from "./AnnouncementsGroups";
import AnnouncementsView from "./AnnouncementsView";
import { announcementsMockData } from "../../../mocks/notifications";

const AnnouncementsPage = (): React.ReactElement => {
const [announcements, setAnnouncements] = useState<GroupAnnouncements>({});
const [selectedGroup, setSelectedGroup] = useState<string>("");

useEffect(() => {
// TODO: Fetch announcements from API
const combinedAnnouncements: GroupAnnouncements = {};
Object.entries(announcementsMockData).forEach(([key, value]) => {
for (let i = 0; i < value.length; i += 1) {
const newAnnouncement: Announcement = {
room: key,
author: value[i].author,
message: value[i].message,
createdAt: value[i].createdAt,
};
// check if alr exists, if not create new
if (!combinedAnnouncements[key]) {
combinedAnnouncements[key] = [];
}
combinedAnnouncements[key].push(newAnnouncement);
}
});

setAnnouncements(combinedAnnouncements);
}, []);

return (
<Flex flexDir="column" flexGrow={1}>
<Flex flexDir="row" alignItems="flex-start" w="100%" flexGrow={1}>
<AnnouncementsGroups
announcements={announcements}
setSelectedGroup={setSelectedGroup}
/>
<AnnouncementsView
announcements={announcements}
selectedGroup={selectedGroup}
/>
</Flex>
</Flex>
);
};

export default AnnouncementsPage;
70 changes: 70 additions & 0 deletions frontend/src/components/pages/home/AnnouncementNotification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { useState } from "react";
import moment from "moment";
import { Box, Text, Flex, Icon, IconButton } from "@chakra-ui/react";
import PersonOutlineOutlinedIcon from "@mui/icons-material/PersonOutlineOutlined";
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import ExpandLessIcon from "@mui/icons-material/ExpandLess";

import { Announcement } from "../../../types/NotificationTypes";

const AnnouncementNotification = ({
room,
message,
createdAt,
}: Announcement): React.ReactElement => {
const [showFullMessage, setShowFullMessage] = useState(false);

return (
<Box w="100%" p={3}>
<Flex alignItems="center">
<Box
borderRadius="full"
border="2px solid"
borderColor="gray.300"
p={1}
mr={3}
>
<Icon
as={PersonOutlineOutlinedIcon}
boxSize={10}
color="purple.main"
/>
</Box>
<Flex flexDir="column" w="80%">
<Flex alignItems="baseline" w="100%">
<Text as="b" mr={4}>
{"Admin to Room ".concat(room)}
</Text>
<Text color="gray.500" fontSize="sm">
posted at {moment(createdAt).format("h:mm a")}
</Text>
</Flex>
<Box w="80%">
{showFullMessage ? (
<Text mt={1}>{message}</Text>
) : (
<Text
mt={1}
overflow="hidden"
textOverflow="ellipsis"
whiteSpace="nowrap"
>
{message}
</Text>
)}
</Box>
</Flex>
<IconButton
aria-label="expand"
bg="white"
_hover={{ bg: "white" }}
onClick={() => setShowFullMessage(!showFullMessage)}
icon={showFullMessage ? <ChevronRightIcon /> : <ExpandLessIcon />}
size="md"
/>
</Flex>
</Box>
);
};

export default AnnouncementNotification;
89 changes: 89 additions & 0 deletions frontend/src/components/pages/home/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { useState, useEffect } from "react";
import { Flex, Box, Heading, Text } from "@chakra-ui/react";
import { announcementsMockData } from "../../../mocks/notifications";
import AnnouncementNotification from "./AnnouncementNotification";
import { Announcement } from "../../../types/NotificationTypes";

const HomePage = (): React.ReactElement => {
const [numberPosts, setNumberPosts] = useState(0);
const [viewAll, setViewAll] = useState(false);
const [announcements, setAnnouncements] = useState<Announcement[]>([]);
const [recentAnnouncements, setRecentAnnouncements] = useState<
Announcement[]
>([]);

useEffect(() => {
// Combine all announcements into a single array
const combinedAnnouncements: Announcement[] = [];
Object.entries(announcementsMockData).forEach(([key, value]) => {
for (let i = 0; i < value.length; i += 1) {
const newAnnouncement: Announcement = {
room: key,
author: value[i].author,
message: value[i].message,
createdAt: value[i].createdAt,
};
combinedAnnouncements.push(newAnnouncement);
}
});

const sortedAnnouncements = combinedAnnouncements.sort(
(a, b) =>
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
);
// Filter announcements from the current week
const oneWeekAgo = new Date();
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
const thisWeeksAnnouncements = sortedAnnouncements.filter(
(announcement) => new Date(announcement.createdAt) >= oneWeekAgo,
);
setAnnouncements(combinedAnnouncements);
setRecentAnnouncements(thisWeeksAnnouncements.slice(0, 3));
setNumberPosts(thisWeeksAnnouncements.length);
}, []);

return (
<Flex flexDirection="column" alignItems="center" w="80vw">
<Box>
<Heading>Home Page</Heading>
</Box>
<Box
border="2px solid grey"
p={6}
justifyContent="space-between"
borderRadius="8px"
w="75%"
>
<Flex justifyContent="space-between" alignItems="center" mb={2}>
<Flex alignItems="baseline">
<Text fontSize="md" as="b">
Announcements
</Text>
<Text ml={6} fontSize="smaller">
{numberPosts === 0
? "You're all caught up!"
: `${numberPosts} new posts today`}
</Text>
</Flex>

<Text onClick={() => setViewAll(!viewAll)} cursor="pointer">
{viewAll ? "View less" : "View all"}
</Text>
</Flex>
{(viewAll ? announcements : recentAnnouncements).map(
(announcement, index) => (
<AnnouncementNotification
room={announcement.room}
author={announcement.author}
message={announcement.message}
createdAt={announcement.createdAt}
key={index}
/>
),
)}
</Box>
</Flex>
);
};

export default HomePage;
2 changes: 2 additions & 0 deletions frontend/src/constants/Routes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export const HOME_PAGE = "/";

export const ANNOUNCEMENTS_PAGE = "/announcements";

export const LOGIN_PAGE = "/login";

export const SIGNUP_PAGE = "/signup";
Expand Down
1 change: 1 addition & 0 deletions frontend/src/types/NotificationTypes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export interface Announcement {
author: string;
room: string;
message: string;
createdAt: string;
}
Expand Down

0 comments on commit c8081ed

Please sign in to comment.