Skip to content

Commit 9cd001a

Browse files
authored
Merge pull request #44 from Cainuse/notifications
Notifications
2 parents 62e545f + 05fd104 commit 9cd001a

File tree

11 files changed

+519
-25
lines changed

11 files changed

+519
-25
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"axios": "^0.19.2",
1313
"babel-loader": "^8.1.0",
1414
"dotenv": "^8.2.0",
15+
"moment": "^2.27.0",
1516
"react": "^16.13.1",
1617
"react-dom": "^16.13.1",
1718
"react-google-login": "^5.1.20",

src/components/AddOffering/AddOffering.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ class AddOffering extends React.Component {
172172
this.state.comment,
173173
this.state.addedItems,
174174
this.props.currentUser,
175-
this.props.itemDetail._id,
175+
this.props.itemDetail._id
176176
);
177177

178178
let id = this.props.itemDetail._id;

src/components/Navigation/NavBar/ActionBtns/ActionButtons.js

+2-24
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ import { connect } from "react-redux";
33

44
import Button from "@material-ui/core/Button";
55
import { makeStyles } from "@material-ui/core/styles";
6-
import { IconButton } from "@material-ui/core";
76
import AddCircleOutlineOutlinedIcon from "@material-ui/icons/AddCircleOutlineOutlined";
8-
import NotificationsNoneOutlinedIcon from "@material-ui/icons/NotificationsNoneOutlined";
7+
import NotificationsMenu from "./NotificationsMenu";
98

10-
import { unsetUser } from "../../../../redux/actions/userActions";
119
import {
1210
openPostingModal,
1311
openLoginModal,
@@ -41,10 +39,6 @@ const loggedInStyles = makeStyles(() => ({
4139
fontSize: "1.3rem",
4240
fontWeight: "100",
4341
},
44-
notificationBtn: {
45-
fontSize: "1.7rem",
46-
padding: "5px",
47-
},
4842
accountBtn: {
4943
fontSize: "2rem",
5044
padding: "5px",
@@ -91,18 +85,6 @@ const LoginBtn = (props) => {
9185
);
9286
};
9387

94-
const NotificationBtn = (props) => {
95-
return (
96-
<IconButton
97-
className={props.iconBtnClass}
98-
color="inherit"
99-
aria-label="chat"
100-
>
101-
<NotificationsNoneOutlinedIcon className={props.notificationBtnClass} />
102-
</IconButton>
103-
);
104-
};
105-
10688
/**
10789
* MAIN: Logged Out Action Item Components
10890
**/
@@ -117,10 +99,7 @@ const LoggedInActionItems = (props) => {
11799
openPostingModal={props.openPostingModal}
118100
/>
119101
<AppBarDivider className={classes.divider} />
120-
<NotificationBtn
121-
iconBtnClass={classes.iconBtn}
122-
notificationBtnClass={classes.notificationBtn}
123-
/>
102+
<NotificationsMenu />
124103
<AccountBtn
125104
iconBtnClass={classes.iconBtn}
126105
accountBtnClass={classes.accountBtn}
@@ -139,5 +118,4 @@ const ActionItems = (props) => {
139118
export default connect(null, {
140119
openPostingModal,
141120
openLoginModal,
142-
unsetUser,
143121
})(ActionItems);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
import React, { useState } from "react";
2+
import { connect } from "react-redux";
3+
import { ListItemAvatar, ListItemText } from "@material-ui/core";
4+
import { makeStyles } from "@material-ui/core/styles";
5+
import IconButton from "@material-ui/core/IconButton";
6+
import LocalOfferIcon from "@material-ui/icons/LocalOffer";
7+
import Menu from "@material-ui/core/Menu";
8+
import MenuItem from "@material-ui/core/MenuItem";
9+
import moment from "moment";
10+
import Typography from "@material-ui/core/Typography";
11+
import ClearIcon from "@material-ui/icons/Clear";
12+
import CheckIcon from "@material-ui/icons/Check";
13+
import ErrorIcon from "@material-ui/icons/Error";
14+
import CancelIcon from "@material-ui/icons/Cancel";
15+
import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
16+
import CheckBoxIcon from "@material-ui/icons/CheckBox";
17+
import MarkunreadIcon from "@material-ui/icons/Markunread";
18+
import Button from "@material-ui/core/Button";
19+
import {
20+
updateNotificationAsync,
21+
removeNotificationAsync,
22+
} from "../../../../redux/actions/notificationActions";
23+
24+
const useStyles = makeStyles(() => ({
25+
acceptedIcon: {
26+
color: "green",
27+
},
28+
rejectedIcon: {
29+
color: "red",
30+
},
31+
moreItems: {
32+
textTransform: "none",
33+
},
34+
}));
35+
36+
const SeeMoreMenu = ({
37+
dispatch,
38+
handleDeleteClick,
39+
onUpdateStatus,
40+
_id,
41+
isRead,
42+
}) => {
43+
const [anchorEl, setAnchorEl] = useState(null);
44+
const classes = useStyles();
45+
const open = Boolean(anchorEl);
46+
47+
const handleClick = (event) => {
48+
setAnchorEl(event.currentTarget);
49+
};
50+
51+
const handleClose = () => {
52+
setAnchorEl(null);
53+
};
54+
55+
const handleReadClick = () => {
56+
dispatch(updateNotificationAsync(_id, !isRead)).then(() => {
57+
onUpdateStatus(_id, !isRead);
58+
});
59+
};
60+
61+
return (
62+
<div>
63+
<IconButton
64+
aria-label="more"
65+
aria-controls="more-menu"
66+
aria-haspopup="true"
67+
onClick={handleClick}
68+
>
69+
<MoreHorizIcon />
70+
</IconButton>
71+
<Menu
72+
id="more-menu"
73+
anchorEl={anchorEl}
74+
anchorOrigin={{
75+
vertical: "bottom",
76+
horizontal: "center",
77+
}}
78+
transformOrigin={{
79+
vertical: "top",
80+
horizontal: "center",
81+
}}
82+
keepMounted
83+
open={open}
84+
onClose={handleClose}
85+
>
86+
<MenuItem onClick={handleClose}>
87+
<Button
88+
color="inherit"
89+
onClick={handleReadClick}
90+
className={classes.moreItems}
91+
startIcon={isRead ? <MarkunreadIcon /> : <CheckIcon />}
92+
>
93+
{isRead ? "Mark as unread" : "Mark as read"}
94+
</Button>
95+
</MenuItem>
96+
<MenuItem onClick={handleClose}>
97+
<Button
98+
color="inherit"
99+
onClick={handleDeleteClick}
100+
className={classes.moreItems}
101+
startIcon={<ClearIcon />}
102+
>
103+
Clear
104+
</Button>
105+
</MenuItem>
106+
</Menu>
107+
</div>
108+
);
109+
};
110+
111+
const Notification = ({
112+
dispatch,
113+
_id,
114+
type,
115+
date,
116+
isRead,
117+
content,
118+
key,
119+
onUpdateStatus,
120+
}) => {
121+
const classes = useStyles();
122+
123+
const [isExisting, setIsExisting] = useState(true);
124+
125+
const handleDeleteClick = () => {
126+
dispatch(removeNotificationAsync(_id)).then(() => {
127+
setIsExisting(false);
128+
});
129+
};
130+
131+
const getItemAvatar = (type) => {
132+
if (type === "newOffering") {
133+
return <LocalOfferIcon color="primary" />;
134+
} else if (type === "offeringAccepted") {
135+
return <CheckBoxIcon className={classes.acceptedIcon} />;
136+
} else if (type === "offeringRejected") {
137+
return <CancelIcon className={classes.rejectedIcon} />;
138+
} else {
139+
return <ErrorIcon />;
140+
}
141+
};
142+
143+
return isExisting ? (
144+
<MenuItem selected={!isRead} divider={true} key={key}>
145+
<ListItemAvatar>{getItemAvatar(type)}</ListItemAvatar>
146+
147+
<ListItemText
148+
primary={content}
149+
primaryTypographyProps={{
150+
style: { whiteSpace: "normal", wordWrap: "break-word" },
151+
}}
152+
secondary={moment(date).format("MMMM Do YYYY, h:mm a")}
153+
/>
154+
155+
<SeeMoreMenu
156+
dispatch={dispatch}
157+
handleDeleteClick={handleDeleteClick}
158+
onUpdateStatus={onUpdateStatus}
159+
_id={_id}
160+
isRead={isRead}
161+
className={classes.seeMoreMenu}
162+
/>
163+
</MenuItem>
164+
) : null;
165+
};
166+
167+
export default connect()(Notification);

0 commit comments

Comments
 (0)