Skip to content

Commit

Permalink
Implement in-app notification logic
Browse files Browse the repository at this point in the history
  • Loading branch information
lokeshwar777 committed Aug 22, 2024
1 parent f3b4f91 commit ec83f13
Show file tree
Hide file tree
Showing 20 changed files with 637 additions and 281 deletions.
15 changes: 13 additions & 2 deletions src/components/HomePage/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ function HomePage({ background = "white", textColor = "black" }) {
]);

const profileData = useSelector(({ firebase: { profile } }) => profile);

useEffect(() => {
const getFeed = async () => {
const tutorialIdArray = await getTutorialFeedIdArray(profileData.uid)(
Expand All @@ -184,7 +185,13 @@ function HomePage({ background = "white", textColor = "black" }) {
}) => homepageFeedArray
);

const notification = () => {};
const notifications = useSelector(
state => state.notifications.data.notifications
);
const notificationCount = notifications?.filter(
notification => !notification.isRead
).length;

const handleChange = (event, newValue) => {
setValue(newValue);
};
Expand Down Expand Up @@ -217,7 +224,11 @@ function HomePage({ background = "white", textColor = "black" }) {
}}
>
<Grid item className={classes.outerSideBar}>
<SideBar open={openMenu} toggleSlider={toggleSlider} />
<SideBar
open={openMenu}
toggleSlider={toggleSlider}
notificationCount={notificationCount}
/>
</Grid>
</Grid>
)}
Expand Down
11 changes: 8 additions & 3 deletions src/components/NavBar/new/MainNavbar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import LeftMenu from "./LeftMenu";
import { useHistory } from "react-router-dom";
import MenuIcon from "@mui/icons-material/Menu";
import CloseIcon from "@mui/icons-material/Close";

import { useSelector } from "react-redux";
import SideBar from "../../../SideBar/index";
import useWindowSize from "../../../../helpers/customHooks/useWindowSize";

Expand Down Expand Up @@ -64,7 +64,12 @@ function MainNavbar() {
const toggleSlider = () => {
setOpen(!openMenu);
};
const notification = () => {};
const notifications = useSelector(
state => state.notifications.data.notifications
);
const notificationCount = notifications?.filter(
notification => !notification.isRead
).length;
return (
<Headroom>
<nav
Expand Down Expand Up @@ -137,7 +142,7 @@ function MainNavbar() {
<SideBar
open={openMenu}
toggleSlider={toggleSlider}
notification={notification}
notificationCount={notificationCount}
drawWidth={960}
/>
)}
Expand Down
10 changes: 8 additions & 2 deletions src/components/NavBar/new/MiniNavbar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import MenuIcon from "@mui/icons-material/Menu";
import CloseIcon from "@mui/icons-material/Close";
import SideBar from "../../../SideBar";
import useWindowSize from "../../../../helpers/customHooks/useWindowSize";
import { useSelector } from "react-redux";

const useStyles = makeStyles(theme => ({
input: {
Expand Down Expand Up @@ -66,7 +67,12 @@ function MiniNavbar() {
const classes = useStyles();

const history = useHistory();
const notification = () => {};
const notifications = useSelector(
state => state.notifications.data.notifications
);
const notificationCount = notifications?.filter(
notification => !notification.isRead
).length;
const [openDrawer, setOpenDrawer] = React.useState(false);
const [openMenu, setOpen] = useState(false);
const toggleSlider = () => {
Expand Down Expand Up @@ -261,7 +267,7 @@ function MiniNavbar() {
<SideBar
open={openMenu}
toggleSlider={toggleSlider}
notification={notification}
notificationCount={notificationCount}
>
{window.innerWidth <= 960 && (
<>
Expand Down
161 changes: 105 additions & 56 deletions src/components/Notification/NotificationBox.jsx
Original file line number Diff line number Diff line change
@@ -1,85 +1,134 @@
import React from "react";
import { Grid, Card, Menu, MenuItem } from "@mui/material";
import IconButton from "@mui/material/IconButton";
import MoreHorizOutlinedIcon from "@mui/icons-material/MoreHorizOutlined";
import Typography from "@mui/material/Typography";
import Avatar from "@mui/material/Avatar";
import Box from "@mui/material/Box";
import { Link } from "react-router-dom";
import useStyles from "./styles";
import { notifications } from "./notifications";
import { useState, useRef } from "react";
import { blue } from "@mui/material/colors";
import { readNotification, deleteNotification } from "../../store/actions";
import { useFirebase, useFirestore } from "react-redux-firebase";
import { useDispatch } from "react-redux";

const NotificationBox = ({ notification }) => {
const NotificationBox = ({ notification, onDelete }) => {
const classes = useStyles();
const anchorRef = useRef();
const firebase = useFirebase();
const firestore = useFirestore();
const dispatch = useDispatch();
const [open, setOpen] = useState(false);
const handleClose = () => {
setOpen(false);
};
const handleRead = () => {
const handleRead = async () => {
notification.isRead = true;
await readNotification(notification.notification_id)(
firebase,
firestore,
dispatch
);
handleClose();
};
const handleDelete = id => {
notifications.filter(notification => id != notification.id);
const handleDelete = async () => {
await deleteNotification(notification.notification_id)(
firebase,
firestore,
dispatch
);
await onDelete(notification.notification_id);
};

const getRelativeTime = timestamp => {
const now = new Date();
const createdAt = timestamp.toDate();
const diff = Math.floor((now - createdAt) / 1000);

if (diff < 60) {
return `${diff} seconds ago`;
} else if (diff < 3600) {
const minutes = Math.floor(diff / 60);
return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
} else if (diff < 86400) {
const hours = Math.floor(diff / 3600);
return `${hours} hour${hours > 1 ? "s" : ""} ago`;
} else {
const days = Math.floor(diff / 86400);
return `${days} day${days > 1 ? "s" : ""} ago`;
}
};

return (
<>
<Card
className={classes.Notification}
style={{
backgroundColor: notification.isRead ? "#fff" : blue[50],
borderRadius: "16px"
<Card
className={classes.Notification}
style={{
backgroundColor: notification.isRead ? "#fff" : blue[50],
borderRadius: "16px",
padding: "16px",
position: "relative",
display: "flex",
flexDirection: "row",
alignItems: "center",
gap: "16px"
}}
>
{!notification.isRead && <Box className={classes.unread}></Box>}
<Avatar
aria-label="recipe"
className={classes.avatar}
data-testId="UserAvatar"
sx={{
width: "60px",
height: "60px"
}}
>
{!notification.isRead && <Box className={classes.unread}></Box>}
<Avatar
aria-label="recipe"
className={classes.avatar}
data-testId="UserAvatar"
sx={{
width: "60px",
height: "60px"
}}
S
</Avatar>
<Box>
<Typography>
<span style={{ fontWeight: "600" }}>{notification.username}</span>{" "}
from <span style={{ fontWeight: "600" }}>{notification.org}</span>
</Typography>
<Typography className={classes.time}>
{getRelativeTime(notification.createdAt)}
</Typography>
<Typography sx={{ fontSize: "0.8rem" }}>
{notification.content}
</Typography>
<Link
to={`/tutorial/${notification?.tutorial_id}`}
onClick={handleRead}
>
S
</Avatar>
<Box>
<Typography>
<span style={{ fontWeight: "600" }}>{notification.username}</span>{" "}
from <span style={{ fontWeight: "600" }}>Codelabz</span>
<Typography variant="body2" color="primary">
View tutorial
</Typography>
<Typography className={classes.time}>
{notification.timestamp}
</Typography>
<Typography sx={{ fontSize: "0.8rem" }}>
{notification.message}
</Typography>
</Box>
<div>
<IconButton
ref={anchorRef}
onClick={() => {
setOpen(true);
}}
aria-label="share"
data-testId="MoreIcon"
style={{ position: "absolute", top: 0, right: 0 }}
>
<MoreHorizOutlinedIcon />
</IconButton>
<Menu anchorEl={anchorRef.current} open={open} onClose={handleClose}>
</Link>
</Box>
<div>
<IconButton
ref={anchorRef}
onClick={() => {
setOpen(true);
}}
aria-label="share"
data-testId="MoreIcon"
style={{ position: "absolute", top: 0, right: 0 }}
>
<MoreHorizOutlinedIcon />
</IconButton>
<Menu anchorEl={anchorRef.current} open={open} onClose={handleClose}>
{!notification.isRead && (
<MenuItem onClick={handleRead}>Mark as read</MenuItem>
<MenuItem onClick={() => handleDelete(notification.id)}>
Delete
</MenuItem>
<MenuItem onClick={handleClose}>
Block {notification.username}
</MenuItem>
</Menu>
</div>
</Card>
</>
)}
<MenuItem onClick={() => handleDelete()}>Delete</MenuItem>
<MenuItem onClick={handleClose}>
Block {notification.username}
</MenuItem>
</Menu>
</div>
</Card>
);
};

Expand Down
Loading

0 comments on commit ec83f13

Please sign in to comment.